From b9f4403408d1fcebff811eda4b6c8d1f7dcccf6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 19 Jul 2024 14:46:42 +0200 Subject: [PATCH 001/186] Add simplified sliding sync toggle to developer options --- .../impl/developer/DeveloperSettingsEvents.kt | 1 + .../developer/DeveloperSettingsPresenter.kt | 7 ++++++ .../impl/developer/DeveloperSettingsState.kt | 1 + .../DeveloperSettingsStateProvider.kt | 2 ++ .../impl/developer/DeveloperSettingsView.kt | 9 ++++++++ .../DeveloperSettingsPresenterTest.kt | 22 +++++++++++++++++++ .../developer/DeveloperSettingsViewTest.kt | 13 +++++++++++ libraries/matrix/impl/build.gradle.kts | 5 +++-- .../libraries/matrix/impl/RustMatrixClient.kt | 3 +++ .../matrix/impl/RustMatrixClientFactory.kt | 12 +++++++++- .../api/store/AppPreferencesStore.kt | 3 +++ .../impl/store/DefaultAppPreferencesStore.kt | 13 +++++++++++ .../test/InMemoryAppPreferencesStore.kt | 10 +++++++++ 13 files changed, 98 insertions(+), 3 deletions(-) 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 58f7ac7c02..bb0252e04d 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,5 +21,6 @@ import io.element.android.libraries.featureflag.ui.model.FeatureUiModel sealed interface DeveloperSettingsEvents { data class UpdateEnabledFeature(val feature: FeatureUiModel, val isEnabled: Boolean) : DeveloperSettingsEvents data class SetCustomElementCallBaseUrl(val baseUrl: String?) : DeveloperSettingsEvents + data class SetSimplifiedSlidingSyncEnabled(val isEnabled: Boolean) : DeveloperSettingsEvents data object ClearCache : 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 8295b815c9..4f4b833367 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 @@ -75,6 +75,9 @@ class DeveloperSettingsPresenter @Inject constructor( val customElementCallBaseUrl by appPreferencesStore .getCustomElementCallBaseUrlFlow() .collectAsState(initial = null) + val isSimplifiedSlidingSyncEnabled by appPreferencesStore + .isSimplifiedSlidingSyncEnabledFlow() + .collectAsState(initial = false) LaunchedEffect(Unit) { FeatureFlags.entries @@ -114,6 +117,9 @@ class DeveloperSettingsPresenter @Inject constructor( appPreferencesStore.setCustomElementCallBaseUrl(urlToSave) } DeveloperSettingsEvents.ClearCache -> coroutineScope.clearCache(clearCacheAction) + is DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled -> coroutineScope.launch { + appPreferencesStore.setSimplifiedSlidingSyncEnabled(event.isEnabled) + } } } @@ -127,6 +133,7 @@ class DeveloperSettingsPresenter @Inject constructor( defaultUrl = ElementCallConfig.DEFAULT_BASE_URL, validator = ::customElementCallUrlValidator, ), + isSimpleSlidingSyncEnabled = isSimplifiedSlidingSyncEnabled, eventSink = ::handleEvents ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsState.kt index 9a12823686..91cf7051c3 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsState.kt @@ -27,6 +27,7 @@ data class DeveloperSettingsState( val rageshakeState: RageshakePreferencesState, val clearCacheAction: AsyncData, val customElementCallBaseUrlState: CustomElementCallBaseUrlState, + val isSimpleSlidingSyncEnabled: Boolean, val eventSink: (DeveloperSettingsEvents) -> Unit ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsStateProvider.kt index fb93a63ffc..01c2971777 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsStateProvider.kt @@ -39,6 +39,7 @@ open class DeveloperSettingsStateProvider : PreviewParameterProvider = AsyncData.Uninitialized, customElementCallBaseUrlState: CustomElementCallBaseUrlState = aCustomElementCallBaseUrlState(), + isSimplifiedSlidingSyncEnabled: Boolean = false, eventSink: (DeveloperSettingsEvents) -> Unit = {}, ) = DeveloperSettingsState( features = aFeatureUiModelList(), @@ -46,6 +47,7 @@ fun aDeveloperSettingsState( cacheSize = AsyncData.Success("1.2 MB"), clearCacheAction = clearCacheAction, customElementCallBaseUrlState = customElementCallBaseUrlState, + isSimpleSlidingSyncEnabled = isSimplifiedSlidingSyncEnabled, eventSink = eventSink, ) 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 dd684fcaaa..3fab690191 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 @@ -26,6 +26,7 @@ import io.element.android.features.preferences.impl.R import io.element.android.features.rageshake.api.preferences.RageshakePreferencesView import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory import io.element.android.libraries.designsystem.components.preferences.PreferencePage +import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch import io.element.android.libraries.designsystem.components.preferences.PreferenceText import io.element.android.libraries.designsystem.components.preferences.PreferenceTextField import io.element.android.libraries.designsystem.preview.ElementPreview @@ -60,6 +61,14 @@ fun DeveloperSettingsView( title = "Configure tracing", onClick = onOpenConfigureTracing, ) + PreferenceSwitch( + title = "Enable Simplified Sliding Sync", + subtitle = "This option requires an app restart to work.", + isChecked = state.isSimpleSlidingSyncEnabled, + onCheckedChange = { + state.eventSink(DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled(it)) + } + ) } PreferenceCategory(title = "Showkase") { PreferenceText( 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 113125d950..4c7a16f8cd 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 @@ -35,6 +35,7 @@ import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.awaitLastSequentialItem +import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -55,6 +56,7 @@ class DeveloperSettingsPresenterTest { assertThat(initialState.cacheSize).isEqualTo(AsyncData.Uninitialized) assertThat(initialState.customElementCallBaseUrlState).isNotNull() assertThat(initialState.customElementCallBaseUrlState.baseUrl).isNull() + assertThat(initialState.isSimpleSlidingSyncEnabled).isFalse() val loadedState = awaitItem() assertThat(loadedState.rageshakeState.isEnabled).isFalse() assertThat(loadedState.rageshakeState.isSupported).isTrue() @@ -160,6 +162,26 @@ class DeveloperSettingsPresenterTest { } } + @Test + fun `present - toggling simplified sliding sync changes the preferences`() = runTest { + val preferences = InMemoryAppPreferencesStore() + val presenter = createDeveloperSettingsPresenter(preferencesStore = preferences) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitLastSequentialItem() + assertThat(initialState.isSimpleSlidingSyncEnabled).isFalse() + + initialState.eventSink(DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled(true)) + assertThat(awaitItem().isSimpleSlidingSyncEnabled).isTrue() + assertThat(preferences.isSimplifiedSlidingSyncEnabledFlow().first()).isTrue() + + initialState.eventSink(DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled(false)) + assertThat(awaitItem().isSimpleSlidingSyncEnabled).isFalse() + assertThat(preferences.isSimplifiedSlidingSyncEnabledFlow().first()).isFalse() + } + } + private fun createDeveloperSettingsPresenter( featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(), cacheSizeUseCase: FakeComputeCacheSizeUseCase = FakeComputeCacheSizeUseCase(), diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt index 7288b76d3c..aa993c39bc 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt @@ -109,6 +109,19 @@ class DeveloperSettingsViewTest { rule.onNodeWithText("Clear cache").performClick() eventsRecorder.assertSingle(DeveloperSettingsEvents.ClearCache) } + + @Config(qualifiers = "h1500dp") + @Test + fun `clicking on the simplified sliding sync switch emits the expected event`() { + val eventsRecorder = EventsRecorder() + rule.setDeveloperSettingsView( + state = aDeveloperSettingsState( + eventSink = eventsRecorder + ), + ) + rule.onNodeWithText("Enable Simplified Sliding Sync").performClick() + eventsRecorder.assertSingle(DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled(true)) + } } private fun AndroidComposeTestRule.setDeveloperSettingsView( diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 523ea2fda1..c74cb6ce07 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -37,12 +37,13 @@ dependencies { debugImplementation(libs.matrix.sdk) } implementation(projects.appconfig) - implementation(projects.libraries.di) implementation(projects.libraries.androidutils) + implementation(projects.libraries.di) + implementation(projects.libraries.featureflag.api) implementation(projects.libraries.network) + implementation(projects.libraries.preferences.api) implementation(projects.services.analytics.api) implementation(projects.services.toolbox.api) - implementation(projects.libraries.featureflag.api) api(projects.libraries.matrix.api) implementation(libs.dagger) implementation(projects.libraries.core) 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 db86e1a2a5..1f9a531027 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 @@ -69,6 +69,7 @@ import io.element.android.libraries.matrix.impl.util.anonymizedTokens 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.preferences.api.store.AppPreferencesStore import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.collections.immutable.ImmutableList @@ -126,6 +127,7 @@ class RustMatrixClient( private val baseDirectory: File, baseCacheDirectory: File, private val clock: SystemClock, + private val appPreferencesStore: AppPreferencesStore, ) : MatrixClient { override val sessionId: UserId = UserId(client.userId()) override val deviceId: String = client.deviceId() @@ -554,6 +556,7 @@ class RustMatrixClient( } close() deleteSessionDirectory(deleteCryptoDb = true) + appPreferencesStore.setSimplifiedSlidingSyncEnabled(false) if (removeSession) { sessionStore.removeSession(sessionId.value) } 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 7ddf54a300..f9c2a5b6d1 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 @@ -23,10 +23,12 @@ import io.element.android.libraries.matrix.impl.certificates.UserCertificatesPro import io.element.android.libraries.matrix.impl.proxy.ProxyProvider import io.element.android.libraries.matrix.impl.util.anonymizedTokens import io.element.android.libraries.network.useragent.UserAgentProvider +import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.sessionstorage.api.SessionData import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.ClientBuilder import org.matrix.rustcomponents.sdk.Session @@ -46,9 +48,14 @@ class RustMatrixClientFactory @Inject constructor( private val proxyProvider: ProxyProvider, private val clock: SystemClock, private val utdTracker: UtdTracker, + private val appPreferencesStore: AppPreferencesStore, ) { suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) { - val client = getBaseClientBuilder(sessionData.sessionPath, sessionData.passphrase) + val client = getBaseClientBuilder( + sessionPath = sessionData.sessionPath, + passphrase = sessionData.passphrase, + useSimplifiedSlidingSync = appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first(), + ) .homeserverUrl(sessionData.homeserverUrl) .username(sessionData.userId) .use { it.build() } @@ -70,6 +77,7 @@ class RustMatrixClientFactory @Inject constructor( baseDirectory = baseDirectory, baseCacheDirectory = cacheDirectory, clock = clock, + appPreferencesStore = appPreferencesStore, ).also { Timber.tag(it.toString()).d("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'") } @@ -79,6 +87,7 @@ class RustMatrixClientFactory @Inject constructor( sessionPath: String, passphrase: String?, slidingSyncProxy: String? = null, + useSimplifiedSlidingSync: Boolean = false, ): ClientBuilder { return ClientBuilder() .sessionPath(sessionPath) @@ -88,6 +97,7 @@ class RustMatrixClientFactory @Inject constructor( .addRootCertificates(userCertificatesProvider.provides()) .autoEnableBackups(true) .autoEnableCrossSigning(true) + .simplifiedSlidingSync(useSimplifiedSlidingSync) .run { // Workaround for non-nullable proxy parameter in the SDK, since each call to the ClientBuilder returns a new reference we need to keep proxyProvider.provides()?.let { proxy(it) } ?: this diff --git a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt index 5d12adbe74..73a42a4ff4 100644 --- a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt +++ b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt @@ -28,5 +28,8 @@ interface AppPreferencesStore { suspend fun setTheme(theme: String) fun getThemeFlow(): Flow + suspend fun setSimplifiedSlidingSyncEnabled(enabled: Boolean) + fun isSimplifiedSlidingSyncEnabledFlow(): Flow + suspend fun reset() } diff --git a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt index d25cda96d0..e80c6d60ad 100644 --- a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt +++ b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt @@ -38,6 +38,7 @@ private val Context.dataStore: DataStore by preferencesDataStore(na private val developerModeKey = booleanPreferencesKey("developerMode") private val customElementCallBaseUrlKey = stringPreferencesKey("elementCallBaseUrl") private val themeKey = stringPreferencesKey("theme") +private val simplifiedSlidingSyncKey = booleanPreferencesKey("useSimplifiedSlidingSync") @ContributesBinding(AppScope::class) class DefaultAppPreferencesStore @Inject constructor( @@ -87,6 +88,18 @@ class DefaultAppPreferencesStore @Inject constructor( } } + override suspend fun setSimplifiedSlidingSyncEnabled(enabled: Boolean) { + store.edit { prefs -> + prefs[simplifiedSlidingSyncKey] = enabled + } + } + + override fun isSimplifiedSlidingSyncEnabledFlow(): Flow { + return store.data.map { prefs -> + prefs[simplifiedSlidingSyncKey] ?: false + } + } + override suspend fun reset() { store.edit { it.clear() } } diff --git a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt index c920f8c6b3..432c7a9772 100644 --- a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt +++ b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt @@ -24,10 +24,12 @@ class InMemoryAppPreferencesStore( isDeveloperModeEnabled: Boolean = false, customElementCallBaseUrl: String? = null, theme: String? = null, + simplifiedSlidingSyncEnabled: Boolean = false ) : AppPreferencesStore { private val isDeveloperModeEnabled = MutableStateFlow(isDeveloperModeEnabled) private val customElementCallBaseUrl = MutableStateFlow(customElementCallBaseUrl) private val theme = MutableStateFlow(theme) + private val simplifiedSlidingSyncEnabled = MutableStateFlow(simplifiedSlidingSyncEnabled) override suspend fun setDeveloperModeEnabled(enabled: Boolean) { isDeveloperModeEnabled.value = enabled @@ -53,6 +55,14 @@ class InMemoryAppPreferencesStore( return theme } + override suspend fun setSimplifiedSlidingSyncEnabled(enabled: Boolean) { + simplifiedSlidingSyncEnabled.value = enabled + } + + override fun isSimplifiedSlidingSyncEnabledFlow(): Flow { + return simplifiedSlidingSyncEnabled + } + override suspend fun reset() { // No op } From fa0430927a431dfd4d0b82f863de5337b95daf11 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 19 Jul 2024 12:58:11 +0000 Subject: [PATCH 002/186] Update screenshots --- ...ferences.impl.developer_DeveloperSettingsView_Day_0_en.png | 4 ++-- ...ferences.impl.developer_DeveloperSettingsView_Day_1_en.png | 4 ++-- ...ferences.impl.developer_DeveloperSettingsView_Day_2_en.png | 4 ++-- ...rences.impl.developer_DeveloperSettingsView_Night_0_en.png | 4 ++-- ...rences.impl.developer_DeveloperSettingsView_Night_1_en.png | 4 ++-- ...rences.impl.developer_DeveloperSettingsView_Night_2_en.png | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png index e3a0f6e67e..1aca7ec0cf 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db1631ff53075b31c674cde4bf25cc2876cda8053ffcb593bf6c497c5c41d0c4 -size 49825 +oid sha256:2254c087a6dcf26a725ac3bea499d448c1e652a5f558f400500b6ac47290cea0 +size 55170 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png index e3a0f6e67e..1aca7ec0cf 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db1631ff53075b31c674cde4bf25cc2876cda8053ffcb593bf6c497c5c41d0c4 -size 49825 +oid sha256:2254c087a6dcf26a725ac3bea499d448c1e652a5f558f400500b6ac47290cea0 +size 55170 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png index df320f9fd7..ab696e6c2f 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7f5ea92f8413f6b6dc92d074038727036912ef1828210d0c4d6e36fb0f7e5d3 -size 48352 +oid sha256:e3db370fb5b5be9e6585367634f2d80292b21145a275b4bcbb3f4aea54cb259a +size 53724 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png index 91914c2851..e28bcd2b6d 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ead9e1fe98bc9ffd33d3768e6983964768edbf3bb4c75cd78a82da5ec0eae03b -size 48275 +oid sha256:c38acd466d6d6bc4b0b03d7588fed15532338a37f678baac5cf1902bd5eab5b8 +size 53240 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png index 91914c2851..e28bcd2b6d 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ead9e1fe98bc9ffd33d3768e6983964768edbf3bb4c75cd78a82da5ec0eae03b -size 48275 +oid sha256:c38acd466d6d6bc4b0b03d7588fed15532338a37f678baac5cf1902bd5eab5b8 +size 53240 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png index c3c8c2ac12..df1ab02517 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee30083ec3b87ba84a34bdee7b10d50939f31c596c3358bdca9b914ba001d198 -size 46843 +oid sha256:42582ba2979c38cc0d2f8c3986b22c0dc31f8bc952e39f67669e46f5e42c6239 +size 51792 From 114b12cbc7733f284ffc191ab4e9dc5f635a0dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 19 Jul 2024 15:17:16 +0200 Subject: [PATCH 003/186] Fix build issues --- samples/minimal/build.gradle.kts | 1 + .../kotlin/io/element/android/samples/minimal/MainActivity.kt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/samples/minimal/build.gradle.kts b/samples/minimal/build.gradle.kts index 91cc4bd110..f754b28a4e 100644 --- a/samples/minimal/build.gradle.kts +++ b/samples/minimal/build.gradle.kts @@ -60,6 +60,7 @@ dependencies { implementation(projects.libraries.eventformatter.impl) implementation(projects.libraries.fullscreenintent.impl) implementation(projects.libraries.preferences.impl) + implementation(projects.libraries.preferences.test) implementation(projects.libraries.indicator.impl) implementation(projects.features.invite.impl) implementation(projects.features.roomlist.impl) diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt index d13cc429dc..cab4c09660 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt @@ -33,6 +33,7 @@ import io.element.android.libraries.matrix.impl.analytics.UtdTracker import io.element.android.libraries.matrix.impl.auth.OidcConfigurationProvider import io.element.android.libraries.matrix.impl.auth.RustMatrixAuthenticationService import io.element.android.libraries.network.useragent.SimpleUserAgentProvider +import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.libraries.sessionstorage.api.LoggedInState import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore import io.element.android.services.analytics.noop.NoopAnalyticsService @@ -62,6 +63,7 @@ class MainActivity : ComponentActivity() { proxyProvider = proxyProvider, clock = DefaultSystemClock(), utdTracker = UtdTracker(NoopAnalyticsService()), + appPreferencesStore = InMemoryAppPreferencesStore(), ), passphraseGenerator = NullPassphraseGenerator(), oidcConfigurationProvider = OidcConfigurationProvider(baseDirectory), From ff6ea4323713ce56dc5cfa6d7b170e56acd748df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 19 Jul 2024 16:32:25 +0200 Subject: [PATCH 004/186] Don't reset the SSS toggle when logged out. Instead, force a logout when toggling the option so user needs to log in again and create a new session using SSS. --- .../features/logout/api/LogoutUseCase.kt | 28 ++++++++++++++++ .../logout/impl/DefaultLogoutUseCase.kt | 32 +++++++++++++++++++ .../developer/DeveloperSettingsPresenter.kt | 3 ++ .../impl/developer/DeveloperSettingsView.kt | 2 +- .../DeveloperSettingsPresenterTest.kt | 19 +++++++++-- .../libraries/matrix/impl/RustMatrixClient.kt | 3 -- .../matrix/impl/RustMatrixClientFactory.kt | 1 - 7 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutUseCase.kt create mode 100644 features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCase.kt diff --git a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutUseCase.kt b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutUseCase.kt new file mode 100644 index 0000000000..397f5ebed7 --- /dev/null +++ b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutUseCase.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.logout.api + +/** + * Used to trigger a log out of the current user from any part of the app. + */ +interface LogoutUseCase { + /** + * Log out the current user and then perform any needed cleanup tasks. + * @param ignoreSdkError if true, the SDK error will be ignored and the user will be logged out anyway. + */ + suspend fun logout(ignoreSdkError: Boolean) +} diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCase.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCase.kt new file mode 100644 index 0000000000..52bf0425d4 --- /dev/null +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCase.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.logout.impl + +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.logout.api.LogoutUseCase +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.MatrixClient +import javax.inject.Inject + +@ContributesBinding(SessionScope::class) +class DefaultLogoutUseCase @Inject constructor( + private val matrixClient: MatrixClient +) : LogoutUseCase { + override suspend fun logout(ignoreSdkError: Boolean) { + matrixClient.logout(ignoreSdkError = ignoreSdkError) + } +} 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 4f4b833367..7b95463ac8 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 @@ -28,6 +28,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.snapshots.SnapshotStateMap import io.element.android.appconfig.ElementCallConfig +import io.element.android.features.logout.api.LogoutUseCase import io.element.android.features.preferences.impl.tasks.ClearCacheUseCase import io.element.android.features.preferences.impl.tasks.ComputeCacheSizeUseCase import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter @@ -55,6 +56,7 @@ class DeveloperSettingsPresenter @Inject constructor( private val rageshakePresenter: RageshakePreferencesPresenter, private val appPreferencesStore: AppPreferencesStore, private val buildMeta: BuildMeta, + private val logoutUseCase: LogoutUseCase, ) : Presenter { @Composable override fun present(): DeveloperSettingsState { @@ -119,6 +121,7 @@ class DeveloperSettingsPresenter @Inject constructor( DeveloperSettingsEvents.ClearCache -> coroutineScope.clearCache(clearCacheAction) is DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled -> coroutineScope.launch { appPreferencesStore.setSimplifiedSlidingSyncEnabled(event.isEnabled) + logoutUseCase.logout(ignoreSdkError = true) } } } 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 3fab690191..f46637e6cb 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 @@ -63,7 +63,7 @@ fun DeveloperSettingsView( ) PreferenceSwitch( title = "Enable Simplified Sliding Sync", - subtitle = "This option requires an app restart to work.", + subtitle = "When toggled you'll be logged out of the app and will need to log in again.", isChecked = state.isSimpleSlidingSyncEnabled, onCheckedChange = { state.eventSink(DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled(it)) 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 4c7a16f8cd..be3c6bbb20 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 @@ -21,6 +21,7 @@ import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.appconfig.ElementCallConfig +import io.element.android.features.logout.api.LogoutUseCase import io.element.android.features.preferences.impl.tasks.FakeClearCacheUseCase import io.element.android.features.preferences.impl.tasks.FakeComputeCacheSizeUseCase import io.element.android.features.rageshake.impl.preferences.DefaultRageshakePreferencesPresenter @@ -163,9 +164,10 @@ class DeveloperSettingsPresenterTest { } @Test - fun `present - toggling simplified sliding sync changes the preferences`() = runTest { + fun `present - toggling simplified sliding sync changes the preferences and logs out the user`() = runTest { + val logoutUseCase = FakeLogoutUseCase() val preferences = InMemoryAppPreferencesStore() - val presenter = createDeveloperSettingsPresenter(preferencesStore = preferences) + val presenter = createDeveloperSettingsPresenter(preferencesStore = preferences, logoutUseCase = logoutUseCase) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -175,10 +177,12 @@ class DeveloperSettingsPresenterTest { initialState.eventSink(DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled(true)) assertThat(awaitItem().isSimpleSlidingSyncEnabled).isTrue() assertThat(preferences.isSimplifiedSlidingSyncEnabledFlow().first()).isTrue() + assertThat(logoutUseCase.logoutCallCount).isEqualTo(1) initialState.eventSink(DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled(false)) assertThat(awaitItem().isSimpleSlidingSyncEnabled).isFalse() assertThat(preferences.isSimplifiedSlidingSyncEnabledFlow().first()).isFalse() + assertThat(logoutUseCase.logoutCallCount).isEqualTo(2) } } @@ -189,6 +193,7 @@ class DeveloperSettingsPresenterTest { rageshakePresenter: DefaultRageshakePreferencesPresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore()), preferencesStore: InMemoryAppPreferencesStore = InMemoryAppPreferencesStore(), buildMeta: BuildMeta = aBuildMeta(), + logoutUseCase: FakeLogoutUseCase = FakeLogoutUseCase() ): DeveloperSettingsPresenter { return DeveloperSettingsPresenter( featureFlagService = featureFlagService, @@ -197,6 +202,16 @@ class DeveloperSettingsPresenterTest { rageshakePresenter = rageshakePresenter, appPreferencesStore = preferencesStore, buildMeta = buildMeta, + logoutUseCase = logoutUseCase, ) } } + +private class FakeLogoutUseCase : LogoutUseCase { + var logoutCallCount = 0 + private set + + override suspend fun logout(ignoreSdkError: Boolean) { + logoutCallCount++ + } +} 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 1f9a531027..db86e1a2a5 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 @@ -69,7 +69,6 @@ import io.element.android.libraries.matrix.impl.util.anonymizedTokens 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.preferences.api.store.AppPreferencesStore import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.collections.immutable.ImmutableList @@ -127,7 +126,6 @@ class RustMatrixClient( private val baseDirectory: File, baseCacheDirectory: File, private val clock: SystemClock, - private val appPreferencesStore: AppPreferencesStore, ) : MatrixClient { override val sessionId: UserId = UserId(client.userId()) override val deviceId: String = client.deviceId() @@ -556,7 +554,6 @@ class RustMatrixClient( } close() deleteSessionDirectory(deleteCryptoDb = true) - appPreferencesStore.setSimplifiedSlidingSyncEnabled(false) if (removeSession) { sessionStore.removeSession(sessionId.value) } 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 f9c2a5b6d1..96d8e4939d 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 @@ -77,7 +77,6 @@ class RustMatrixClientFactory @Inject constructor( baseDirectory = baseDirectory, baseCacheDirectory = cacheDirectory, clock = clock, - appPreferencesStore = appPreferencesStore, ).also { Timber.tag(it.toString()).d("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'") } From a71d7eb2b4fc0146e980393922879676bb5acf4b Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 19 Jul 2024 14:43:41 +0000 Subject: [PATCH 005/186] Update screenshots --- ...ferences.impl.developer_DeveloperSettingsView_Day_0_en.png | 4 ++-- ...ferences.impl.developer_DeveloperSettingsView_Day_1_en.png | 4 ++-- ...ferences.impl.developer_DeveloperSettingsView_Day_2_en.png | 4 ++-- ...rences.impl.developer_DeveloperSettingsView_Night_0_en.png | 4 ++-- ...rences.impl.developer_DeveloperSettingsView_Night_1_en.png | 4 ++-- ...rences.impl.developer_DeveloperSettingsView_Night_2_en.png | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png index 1aca7ec0cf..d46d57762d 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2254c087a6dcf26a725ac3bea499d448c1e652a5f558f400500b6ac47290cea0 -size 55170 +oid sha256:fb9971d6aa7f0734f9a30f83b25a03519f97789618219f0c79efa87d4430ca0f +size 58918 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png index 1aca7ec0cf..d46d57762d 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2254c087a6dcf26a725ac3bea499d448c1e652a5f558f400500b6ac47290cea0 -size 55170 +oid sha256:fb9971d6aa7f0734f9a30f83b25a03519f97789618219f0c79efa87d4430ca0f +size 58918 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png index ab696e6c2f..5119090213 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3db370fb5b5be9e6585367634f2d80292b21145a275b4bcbb3f4aea54cb259a -size 53724 +oid sha256:f44fc0dc3cd92839a7b176b086be75b082a238b9c8cd197f7273b33e7f01c591 +size 57495 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png index e28bcd2b6d..2294fd4c8a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c38acd466d6d6bc4b0b03d7588fed15532338a37f678baac5cf1902bd5eab5b8 -size 53240 +oid sha256:93a6d6723bc89b9660a440848461c1568004d312599d7d2d2b94299d6aa47c0a +size 57037 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png index e28bcd2b6d..2294fd4c8a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c38acd466d6d6bc4b0b03d7588fed15532338a37f678baac5cf1902bd5eab5b8 -size 53240 +oid sha256:93a6d6723bc89b9660a440848461c1568004d312599d7d2d2b94299d6aa47c0a +size 57037 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png index df1ab02517..1e6522216a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42582ba2979c38cc0d2f8c3986b22c0dc31f8bc952e39f67669e46f5e42c6239 -size 51792 +oid sha256:bd7e58a29f370733af1e35531f428d5d2a732c70b9156d66ba590c9c5203f5d6 +size 55689 From d4f8052696f69521c86f13115a703d854ac325c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 19 Jul 2024 19:51:13 +0200 Subject: [PATCH 006/186] Unify the internal `pinunlock.SignOut` and the new `LogoutUseCase` classes --- features/lockscreen/impl/build.gradle.kts | 2 + .../impl/unlock/PinUnlockPresenter.kt | 6 +- .../impl/unlock/di/PinUnlockBindings.kt | 4 +- .../impl/unlock/signout/DefaultSignOut.kt | 40 ------------ .../impl/unlock/DefaultSignOutTest.kt | 61 ------------------- .../impl/unlock/PinUnlockPresenterTest.kt | 14 ++--- .../features/logout/api/LogoutUseCase.kt | 7 ++- .../logout/impl/DefaultLogoutUseCase.kt | 25 +++++--- .../logout/impl/SessionLogoutModule.kt | 36 +++++++++++ .../test/build.gradle.kts} | 16 +++-- .../logout/test/FakeLogoutUseCase.kt} | 18 +++--- features/preferences/impl/build.gradle.kts | 1 + .../DeveloperSettingsPresenterTest.kt | 21 +++---- 13 files changed, 103 insertions(+), 148 deletions(-) delete mode 100644 features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/signout/DefaultSignOut.kt delete mode 100644 features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/DefaultSignOutTest.kt create mode 100644 features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/SessionLogoutModule.kt rename features/{lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/signout/SignOut.kt => logout/test/build.gradle.kts} (64%) rename features/{lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/FakeSignOut.kt => logout/test/src/main/kotlin/io/element/android/features/logout/test/FakeLogoutUseCase.kt} (56%) diff --git a/features/lockscreen/impl/build.gradle.kts b/features/lockscreen/impl/build.gradle.kts index 21f3e05421..b8dc1c5035 100644 --- a/features/lockscreen/impl/build.gradle.kts +++ b/features/lockscreen/impl/build.gradle.kts @@ -41,6 +41,7 @@ dependencies { implementation(projects.libraries.featureflag.api) implementation(projects.libraries.cryptography.api) implementation(projects.libraries.preferences.api) + implementation(projects.features.logout.api) implementation(projects.libraries.uiStrings) implementation(projects.libraries.sessionStorage.api) implementation(projects.services.appnavstate.api) @@ -59,4 +60,5 @@ dependencies { testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.appnavstate.test) + testImplementation(projects.features.logout.test) } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt index db56b8c17b..b563b3ac70 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt @@ -29,7 +29,7 @@ import io.element.android.features.lockscreen.impl.biometric.BiometricUnlockMana import io.element.android.features.lockscreen.impl.pin.PinCodeManager import io.element.android.features.lockscreen.impl.pin.model.PinEntry import io.element.android.features.lockscreen.impl.unlock.keypad.PinKeypadModel -import io.element.android.features.lockscreen.impl.unlock.signout.SignOut +import io.element.android.features.logout.api.LogoutUseCase import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState @@ -41,7 +41,7 @@ import javax.inject.Inject class PinUnlockPresenter @Inject constructor( private val pinCodeManager: PinCodeManager, private val biometricUnlockManager: BiometricUnlockManager, - private val signOut: SignOut, + private val logoutUseCase: LogoutUseCase, private val coroutineScope: CoroutineScope, private val pinUnlockHelper: PinUnlockHelper, ) : Presenter { @@ -179,7 +179,7 @@ class PinUnlockPresenter @Inject constructor( private fun CoroutineScope.signOut(signOutAction: MutableState>) = launch { suspend { - signOut() + logoutUseCase.logout(ignoreSdkError = true) }.runCatchingUpdatingState(signOutAction) } } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/di/PinUnlockBindings.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/di/PinUnlockBindings.kt index ddd62d2fb6..0f71222ebd 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/di/PinUnlockBindings.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/di/PinUnlockBindings.kt @@ -18,9 +18,9 @@ package io.element.android.features.lockscreen.impl.unlock.di import com.squareup.anvil.annotations.ContributesTo import io.element.android.features.lockscreen.impl.unlock.activity.PinUnlockActivity -import io.element.android.libraries.di.AppScope +import io.element.android.libraries.di.SessionScope -@ContributesTo(AppScope::class) +@ContributesTo(SessionScope::class) interface PinUnlockBindings { fun inject(activity: PinUnlockActivity) } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/signout/DefaultSignOut.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/signout/DefaultSignOut.kt deleted file mode 100644 index 2c541911e6..0000000000 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/signout/DefaultSignOut.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2024 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.element.android.features.lockscreen.impl.unlock.signout - -import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.libraries.di.AppScope -import io.element.android.libraries.matrix.api.MatrixClientProvider -import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService -import javax.inject.Inject - -@ContributesBinding(AppScope::class) -class DefaultSignOut @Inject constructor( - private val authenticationService: MatrixAuthenticationService, - private val matrixClientProvider: MatrixClientProvider, -) : SignOut { - override suspend fun invoke(): String? { - val currentSession = authenticationService.getLatestSessionId() - return if (currentSession != null) { - matrixClientProvider.getOrRestore(currentSession) - .getOrThrow() - .logout(ignoreSdkError = true) - } else { - error("No session to sign out") - } - } -} diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/DefaultSignOutTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/DefaultSignOutTest.kt deleted file mode 100644 index 392693d9ef..0000000000 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/DefaultSignOutTest.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2024 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.element.android.features.lockscreen.impl.unlock - -import com.google.common.truth.Truth.assertThat -import io.element.android.features.lockscreen.impl.unlock.signout.DefaultSignOut -import io.element.android.libraries.matrix.test.FakeMatrixClient -import io.element.android.libraries.matrix.test.FakeMatrixClientProvider -import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService -import io.element.android.tests.testutils.lambda.assert -import io.element.android.tests.testutils.lambda.lambdaRecorder -import kotlinx.coroutines.test.runTest -import org.junit.Test - -class DefaultSignOutTest { - private val matrixClient = FakeMatrixClient() - private val authenticationService = FakeMatrixAuthenticationService() - private val matrixClientProvider = FakeMatrixClientProvider(getClient = { Result.success(matrixClient) }) - private val sut = DefaultSignOut(authenticationService, matrixClientProvider) - - @Test - fun `when no active session then it throws`() = runTest { - authenticationService.getLatestSessionIdLambda = { null } - val result = runCatching { sut.invoke() } - assertThat(result.isFailure).isTrue() - } - - @Test - fun `with one active session and successful logout on client`() = runTest { - val logoutLambda = lambdaRecorder { _: Boolean -> null } - authenticationService.getLatestSessionIdLambda = { matrixClient.sessionId } - matrixClient.logoutLambda = logoutLambda - val result = runCatching { sut.invoke() } - assertThat(result.isSuccess).isTrue() - assert(logoutLambda).isCalledOnce() - } - - @Test - fun `with one active session and and failed logout on client`() = runTest { - val logoutLambda = lambdaRecorder { _: Boolean -> error("Failed to logout") } - authenticationService.getLatestSessionIdLambda = { matrixClient.sessionId } - matrixClient.logoutLambda = logoutLambda - val result = runCatching { sut.invoke() } - assertThat(result.isFailure).isTrue() - assert(logoutLambda).isCalledOnce() - } -} diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt index 89d0e92ee2..8299b5a1ab 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt @@ -28,7 +28,7 @@ import io.element.android.features.lockscreen.impl.pin.PinCodeManager import io.element.android.features.lockscreen.impl.pin.model.PinEntry import io.element.android.features.lockscreen.impl.pin.model.assertText import io.element.android.features.lockscreen.impl.unlock.keypad.PinKeypadModel -import io.element.android.features.lockscreen.impl.unlock.signout.SignOut +import io.element.android.features.logout.test.FakeLogoutUseCase import io.element.android.libraries.architecture.AsyncData import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaRecorder @@ -106,9 +106,9 @@ class PinUnlockPresenterTest { @Test fun `present - forgot pin flow`() = runTest { - val signOutLambda = lambdaRecorder { null } - val signOut = FakeSignOut(signOutLambda) - val presenter = createPinUnlockPresenter(this, signOut = signOut) + val signOutLambda = lambdaRecorder { "" } + val signOut = FakeLogoutUseCase(signOutLambda) + val presenter = createPinUnlockPresenter(this, logoutUseCase = signOut) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -135,7 +135,7 @@ class PinUnlockPresenterTest { awaitItem().also { state -> assertThat(state.signOutAction).isInstanceOf(AsyncData.Success::class.java) } - assert(signOutLambda).isCalledOnce().withNoParameter() + assert(signOutLambda).isCalledOnce() } } @@ -147,7 +147,7 @@ class PinUnlockPresenterTest { scope: CoroutineScope, biometricUnlockManager: BiometricUnlockManager = FakeBiometricUnlockManager(), callback: PinCodeManager.Callback = DefaultPinCodeManagerCallback(), - signOut: SignOut = FakeSignOut(), + logoutUseCase: FakeLogoutUseCase = FakeLogoutUseCase(logoutLambda = { "" }), ): PinUnlockPresenter { val pinCodeManager = aPinCodeManager().apply { addCallback(callback) @@ -156,7 +156,7 @@ class PinUnlockPresenterTest { return PinUnlockPresenter( pinCodeManager = pinCodeManager, biometricUnlockManager = biometricUnlockManager, - signOut = signOut, + logoutUseCase = logoutUseCase, coroutineScope = scope, pinUnlockHelper = PinUnlockHelper(biometricUnlockManager, pinCodeManager), ) diff --git a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutUseCase.kt b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutUseCase.kt index 397f5ebed7..a06b7117b1 100644 --- a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutUseCase.kt +++ b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutUseCase.kt @@ -23,6 +23,11 @@ interface LogoutUseCase { /** * Log out the current user and then perform any needed cleanup tasks. * @param ignoreSdkError if true, the SDK error will be ignored and the user will be logged out anyway. + * @return the session id of the logged out user. */ - suspend fun logout(ignoreSdkError: Boolean) + suspend fun logout(ignoreSdkError: Boolean): String + + interface Factory { + fun create(sessionId: String): LogoutUseCase + } } diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCase.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCase.kt index 52bf0425d4..8e5f08a87a 100644 --- a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCase.kt +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCase.kt @@ -17,16 +17,27 @@ package io.element.android.features.logout.impl import com.squareup.anvil.annotations.ContributesBinding +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import io.element.android.features.logout.api.LogoutUseCase -import io.element.android.libraries.di.SessionScope -import io.element.android.libraries.matrix.api.MatrixClient -import javax.inject.Inject +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.matrix.api.MatrixClientProvider +import io.element.android.libraries.matrix.api.core.SessionId -@ContributesBinding(SessionScope::class) -class DefaultLogoutUseCase @Inject constructor( - private val matrixClient: MatrixClient +class DefaultLogoutUseCase @AssistedInject constructor( + @Assisted private val sessionId: String, + private val matrixClientProvider: MatrixClientProvider, ) : LogoutUseCase { - override suspend fun logout(ignoreSdkError: Boolean) { + @ContributesBinding(AppScope::class) + @AssistedFactory + interface Factory : LogoutUseCase.Factory { + override fun create(sessionId: String): DefaultLogoutUseCase + } + + override suspend fun logout(ignoreSdkError: Boolean): String { + val matrixClient = matrixClientProvider.getOrRestore(SessionId(sessionId)).getOrThrow() matrixClient.logout(ignoreSdkError = ignoreSdkError) + return sessionId } } diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/SessionLogoutModule.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/SessionLogoutModule.kt new file mode 100644 index 0000000000..ec725a34a6 --- /dev/null +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/SessionLogoutModule.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.logout.impl + +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import io.element.android.features.logout.api.LogoutUseCase +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder + +@Module +@ContributesTo(SessionScope::class) +object SessionLogoutModule { + @Provides + fun provideLogoutUseCase( + currentSessionIdHolder: CurrentSessionIdHolder, + factory: DefaultLogoutUseCase.Factory, + ): LogoutUseCase { + return factory.create(currentSessionIdHolder.current.value) + } +} diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/signout/SignOut.kt b/features/logout/test/build.gradle.kts similarity index 64% rename from features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/signout/SignOut.kt rename to features/logout/test/build.gradle.kts index f4c91aece6..7be20ef279 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/signout/SignOut.kt +++ b/features/logout/test/build.gradle.kts @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,8 +14,16 @@ * limitations under the License. */ -package io.element.android.features.lockscreen.impl.unlock.signout +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.features.logout.test" +} -interface SignOut { - suspend operator fun invoke(): String? +dependencies { + implementation(libs.coroutines.core) + implementation(projects.tests.testutils) + api(projects.features.logout.api) } diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/FakeSignOut.kt b/features/logout/test/src/main/kotlin/io/element/android/features/logout/test/FakeLogoutUseCase.kt similarity index 56% rename from features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/FakeSignOut.kt rename to features/logout/test/src/main/kotlin/io/element/android/features/logout/test/FakeLogoutUseCase.kt index 883a5bf97b..bbc67765d1 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/FakeSignOut.kt +++ b/features/logout/test/src/main/kotlin/io/element/android/features/logout/test/FakeLogoutUseCase.kt @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,15 +14,15 @@ * limitations under the License. */ -package io.element.android.features.lockscreen.impl.unlock +package io.element.android.features.logout.test -import io.element.android.features.lockscreen.impl.unlock.signout.SignOut -import io.element.android.tests.testutils.simulateLongTask +import io.element.android.features.logout.api.LogoutUseCase +import io.element.android.tests.testutils.lambda.lambdaError -class FakeSignOut( - var lambda: () -> String? = { null } -) : SignOut { - override suspend fun invoke(): String? = simulateLongTask { - lambda() +class FakeLogoutUseCase( + var logoutLambda: (Boolean) -> String = lambdaError() +) : LogoutUseCase { + override suspend fun logout(ignoreSdkError: Boolean): String { + return logoutLambda(ignoreSdkError) } } diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index ead4515360..ec265d739e 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -90,6 +90,7 @@ dependencies { testImplementation(projects.features.ftue.test) testImplementation(projects.features.rageshake.test) testImplementation(projects.features.rageshake.impl) + testImplementation(projects.features.logout.test) testImplementation(projects.features.roomlist.test) testImplementation(projects.libraries.indicator.impl) testImplementation(projects.libraries.pushproviders.test) 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 be3c6bbb20..9fb1c8b37f 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 @@ -21,7 +21,7 @@ import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.appconfig.ElementCallConfig -import io.element.android.features.logout.api.LogoutUseCase +import io.element.android.features.logout.test.FakeLogoutUseCase import io.element.android.features.preferences.impl.tasks.FakeClearCacheUseCase import io.element.android.features.preferences.impl.tasks.FakeComputeCacheSizeUseCase import io.element.android.features.rageshake.impl.preferences.DefaultRageshakePreferencesPresenter @@ -36,6 +36,7 @@ import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.awaitLastSequentialItem +import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -165,7 +166,8 @@ class DeveloperSettingsPresenterTest { @Test fun `present - toggling simplified sliding sync changes the preferences and logs out the user`() = runTest { - val logoutUseCase = FakeLogoutUseCase() + val logoutCallRecorder = lambdaRecorder { "" } + val logoutUseCase = FakeLogoutUseCase(logoutLambda = logoutCallRecorder) val preferences = InMemoryAppPreferencesStore() val presenter = createDeveloperSettingsPresenter(preferencesStore = preferences, logoutUseCase = logoutUseCase) moleculeFlow(RecompositionMode.Immediate) { @@ -177,12 +179,12 @@ class DeveloperSettingsPresenterTest { initialState.eventSink(DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled(true)) assertThat(awaitItem().isSimpleSlidingSyncEnabled).isTrue() assertThat(preferences.isSimplifiedSlidingSyncEnabledFlow().first()).isTrue() - assertThat(logoutUseCase.logoutCallCount).isEqualTo(1) + logoutCallRecorder.assertions().isCalledOnce() initialState.eventSink(DeveloperSettingsEvents.SetSimplifiedSlidingSyncEnabled(false)) assertThat(awaitItem().isSimpleSlidingSyncEnabled).isFalse() assertThat(preferences.isSimplifiedSlidingSyncEnabledFlow().first()).isFalse() - assertThat(logoutUseCase.logoutCallCount).isEqualTo(2) + logoutCallRecorder.assertions().isCalledExactly(times = 2) } } @@ -193,7 +195,7 @@ class DeveloperSettingsPresenterTest { rageshakePresenter: DefaultRageshakePreferencesPresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore()), preferencesStore: InMemoryAppPreferencesStore = InMemoryAppPreferencesStore(), buildMeta: BuildMeta = aBuildMeta(), - logoutUseCase: FakeLogoutUseCase = FakeLogoutUseCase() + logoutUseCase: FakeLogoutUseCase = FakeLogoutUseCase(logoutLambda = { "" }) ): DeveloperSettingsPresenter { return DeveloperSettingsPresenter( featureFlagService = featureFlagService, @@ -206,12 +208,3 @@ class DeveloperSettingsPresenterTest { ) } } - -private class FakeLogoutUseCase : LogoutUseCase { - var logoutCallCount = 0 - private set - - override suspend fun logout(ignoreSdkError: Boolean) { - logoutCallCount++ - } -} From c76ff38f00744fbbf350df0ed34c4113c297e709 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 23 Jul 2024 13:05:59 +0200 Subject: [PATCH 007/186] Pinned messages : introduces banner view --- .../messages/impl/MessagesPresenter.kt | 5 + .../features/messages/impl/MessagesState.kt | 2 + .../messages/impl/MessagesStateProvider.kt | 10 + .../features/messages/impl/MessagesView.kt | 35 +-- .../messages/impl/di/MessagesModule.kt | 32 +++ .../banner/PinnedMessagesBannerEvents.kt | 21 ++ .../banner/PinnedMessagesBannerPresenter.kt | 57 +++++ .../banner/PinnedMessagesBannerState.kt | 25 +++ .../PinnedMessagesBannerStateProvider.kt | 42 ++++ .../pinned/banner/PinnedMessagesBannerView.kt | 204 ++++++++++++++++++ .../messages/impl/MessagesPresenterTest.kt | 4 + .../designsystem/theme/ColorAliases.kt | 8 + 12 files changed, 429 insertions(+), 16 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerEvents.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt 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 b13a95d4f2..7ef5337ba2 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 @@ -39,6 +39,8 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter import io.element.android.features.messages.impl.messagecomposer.MessageComposerState +import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerPresenter +import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.timeline.TimelineEvents import io.element.android.features.messages.impl.timeline.TimelinePresenter @@ -98,6 +100,7 @@ class MessagesPresenter @AssistedInject constructor( private val customReactionPresenter: CustomReactionPresenter, private val reactionSummaryPresenter: ReactionSummaryPresenter, private val readReceiptBottomSheetPresenter: ReadReceiptBottomSheetPresenter, + private val pinnedMessagesBannerPresenter: Presenter, private val networkMonitor: NetworkMonitor, private val snackbarDispatcher: SnackbarDispatcher, private val dispatchers: CoroutineDispatchers, @@ -129,6 +132,7 @@ class MessagesPresenter @AssistedInject constructor( val customReactionState = customReactionPresenter.present() val reactionSummaryState = reactionSummaryPresenter.present() val readReceiptBottomSheetState = readReceiptBottomSheetPresenter.present() + val pinnedMessagesBannerState = pinnedMessagesBannerPresenter.present() val syncUpdateFlow = room.syncUpdateFlow.collectAsState() val userHasPermissionToSendMessage by room.canSendMessageAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = syncUpdateFlow.value) @@ -231,6 +235,7 @@ class MessagesPresenter @AssistedInject constructor( enableVoiceMessages = enableVoiceMessages, appName = buildMeta.applicationName, callState = callState, + pinnedMessagesBannerState = pinnedMessagesBannerState, eventSink = { handleEvents(it) } ) } 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 e8657d70bd..20b173993e 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 @@ -19,6 +19,7 @@ package io.element.android.features.messages.impl import androidx.compose.runtime.Immutable import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.messagecomposer.MessageComposerState +import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.TimelineState import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState @@ -57,6 +58,7 @@ data class MessagesState( val enableVoiceMessages: Boolean, val callState: RoomCallState, val appName: String, + val pinnedMessagesBannerState: PinnedMessagesBannerState, val eventSink: (MessagesEvents) -> Unit ) 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 1396d3e17c..674fe3c9d3 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 @@ -22,6 +22,8 @@ import io.element.android.features.messages.impl.actionlist.anActionListState import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState +import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState +import io.element.android.features.messages.impl.pinned.banner.aPinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.TimelineState import io.element.android.features.messages.impl.timeline.aTimelineItemList import io.element.android.features.messages.impl.timeline.aTimelineState @@ -87,6 +89,12 @@ open class MessagesStateProvider : PreviewParameterProvider { aMessagesState( callState = RoomCallState.DISABLED, ), + aMessagesState( + pinnedMessagesBannerState = aPinnedMessagesBannerState( + pinnedMessagesCount = 4, + currentPinnedMessageIndex = 0, + ), + ), ) } @@ -116,6 +124,7 @@ fun aMessagesState( showReinvitePrompt: Boolean = false, enableVoiceMessages: Boolean = true, callState: RoomCallState = RoomCallState.ENABLED, + pinnedMessagesBannerState: PinnedMessagesBannerState = aPinnedMessagesBannerState(), eventSink: (MessagesEvents) -> Unit = {}, ) = MessagesState( roomId = RoomId("!id:domain"), @@ -142,6 +151,7 @@ fun aMessagesState( enableVoiceMessages = enableVoiceMessages, callState = callState, appName = "Element", + pinnedMessagesBannerState = pinnedMessagesBannerState, eventSink = eventSink, ) 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 24439c0c75..427ab8d10a 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 @@ -68,6 +68,7 @@ import io.element.android.features.messages.impl.messagecomposer.AttachmentsBott import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerView +import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerView import io.element.android.features.messages.impl.timeline.TimelineView import io.element.android.features.messages.impl.timeline.components.JoinCallMenuItem import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet @@ -373,22 +374,24 @@ private fun MessagesViewContent( RectangleShape }, content = { paddingValues -> - TimelineView( - state = state.timelineState, - typingNotificationState = state.typingNotificationState, - onUserDataClick = onUserDataClick, - onLinkClick = onLinkClick, - onMessageClick = onMessageClick, - onMessageLongClick = onMessageLongClick, - onSwipeToReply = onSwipeToReply, - onReactionClick = onReactionClick, - onReactionLongClick = onReactionLongClick, - onMoreReactionsClick = onMoreReactionsClick, - onReadReceiptClick = onReadReceiptClick, - modifier = Modifier.padding(paddingValues), - forceJumpToBottomVisibility = forceJumpToBottomVisibility, - onJoinCallClick = onJoinCallClick, - ) + Box(modifier = Modifier.padding(paddingValues)) { + TimelineView( + state = state.timelineState, + typingNotificationState = state.typingNotificationState, + onUserDataClick = onUserDataClick, + onLinkClick = onLinkClick, + onMessageClick = onMessageClick, + onMessageLongClick = onMessageLongClick, + onSwipeToReply = onSwipeToReply, + onReactionClick = onReactionClick, + onReactionLongClick = onReactionLongClick, + onMoreReactionsClick = onMoreReactionsClick, + onReadReceiptClick = onReadReceiptClick, + forceJumpToBottomVisibility = forceJumpToBottomVisibility, + onJoinCallClick = onJoinCallClick, + ) + PinnedMessagesBannerView(state = state.pinnedMessagesBannerState) + } }, sheetContent = { subcomposing: Boolean -> MessagesViewComposerBottomSheetContents( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt new file mode 100644 index 0000000000..77fafd0887 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.di + +import com.squareup.anvil.annotations.ContributesTo +import dagger.Binds +import dagger.Module +import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerPresenter +import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.di.SessionScope + +@ContributesTo(SessionScope::class) +@Module +interface MessagesModule { + @Binds + fun bindPinnedMessagesBannerPresenter(presenter: PinnedMessagesBannerPresenter): Presenter +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerEvents.kt new file mode 100644 index 0000000000..792db7e3da --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerEvents.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.pinned.banner + +sealed interface PinnedMessagesBannerEvents { + data object MoveToNextPinned : PinnedMessagesBannerEvents +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt new file mode 100644 index 0000000000..fae2483359 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.pinned.banner + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import io.element.android.libraries.architecture.Presenter +import javax.inject.Inject + +class PinnedMessagesBannerPresenter @Inject constructor() : Presenter { + + @Composable + override fun present(): PinnedMessagesBannerState { + var pinnedMessageCount by remember { + mutableIntStateOf(0) + } + var currentPinnedMessageIndex by rememberSaveable { + mutableIntStateOf(0) + } + + fun handleEvent(event: PinnedMessagesBannerEvents) { + when (event) { + is PinnedMessagesBannerEvents.MoveToNextPinned -> { + if (currentPinnedMessageIndex < pinnedMessageCount - 1) { + currentPinnedMessageIndex++ + } else { + currentPinnedMessageIndex = 0 + } + } + } + } + + return PinnedMessagesBannerState( + pinnedMessagesCount = pinnedMessageCount, + currentPinnedMessageIndex = currentPinnedMessageIndex, + eventSink = ::handleEvent + ) + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt new file mode 100644 index 0000000000..6c285d3f68 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.pinned.banner + +data class PinnedMessagesBannerState( + val pinnedMessagesCount: Int, + val currentPinnedMessageIndex: Int, + val eventSink: (PinnedMessagesBannerEvents) -> Unit +) { + val displayBanner = pinnedMessagesCount > 0 && currentPinnedMessageIndex < pinnedMessagesCount +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt new file mode 100644 index 0000000000..c4cce07f94 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.pinned.banner + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider + +internal class PinnedMessagesBannerStateProvider : PreviewParameterProvider { + + override val values: Sequence + get() = sequenceOf( + aPinnedMessagesBannerState(pinnedMessagesCount = 1, currentPinnedMessageIndex = 0), + aPinnedMessagesBannerState(pinnedMessagesCount = 2, currentPinnedMessageIndex = 0), + aPinnedMessagesBannerState(pinnedMessagesCount = 4, currentPinnedMessageIndex = 0), + aPinnedMessagesBannerState(pinnedMessagesCount = 4, currentPinnedMessageIndex = 1), + aPinnedMessagesBannerState(pinnedMessagesCount = 4, currentPinnedMessageIndex = 2), + aPinnedMessagesBannerState(pinnedMessagesCount = 4, currentPinnedMessageIndex = 3), + ) +} + +internal fun aPinnedMessagesBannerState( + pinnedMessagesCount: Int = 0, + currentPinnedMessageIndex: Int = -1, + eventSink: (PinnedMessagesBannerEvents) -> Unit = {} +) = PinnedMessagesBannerState( + pinnedMessagesCount = pinnedMessagesCount, + currentPinnedMessageIndex = currentPinnedMessageIndex, + eventSink = eventSink +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt new file mode 100644 index 0000000000..38e3562c5f --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(ExperimentalFoundationApi::class) + +package io.element.android.features.messages.impl.pinned.banner + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement.spacedBy +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextButton +import io.element.android.libraries.designsystem.theme.pinnedMessageBannerBorder +import io.element.android.libraries.designsystem.theme.pinnedMessageBannerIndicator +import io.element.android.libraries.designsystem.utils.annotatedTextWithBold + +@Composable +fun PinnedMessagesBannerView( + state: PinnedMessagesBannerState, + modifier: Modifier = Modifier, +) { + if (!state.displayBanner) return + + val borderColor = ElementTheme.colors.pinnedMessageBannerBorder + Row( + modifier = modifier + .background(color = ElementTheme.colors.bgCanvasDefault) + .fillMaxWidth() + .drawBehind { + val strokeWidth = 0.5.dp.toPx() + val y = size.height - strokeWidth / 2 + drawLine( + borderColor, + Offset(0f, y), + Offset(size.width, y), + strokeWidth + ) + drawLine( + borderColor, + Offset(0f, 0f), + Offset(size.width, 0f), + strokeWidth + ) + } + .shadow(elevation = 5.dp, spotColor = Color.Transparent) + .heightIn(min = 64.dp) + .clickable { + state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + }, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = spacedBy(10.dp) + ) { + Spacer(modifier = Modifier.width(16.dp)) + PinIndicators( + pinIndex = state.currentPinnedMessageIndex, + pinsCount = state.pinnedMessagesCount, + modifier = Modifier.heightIn(max = 40.dp) + ) + Icon( + imageVector = CompoundIcons.PinSolid(), + contentDescription = null, + tint = ElementTheme.materialColors.secondary, + modifier = Modifier.size(20.dp) + ) + PinnedMessageItem( + index = state.currentPinnedMessageIndex, + totalCount = state.pinnedMessagesCount, + message = "This is a pinned message", + modifier = Modifier.weight(1f) + ) + TextButton(text = "View all", onClick = { /*TODO*/ }) + } +} + +@Composable +private fun PinIndicators( + pinIndex: Int, + pinsCount: Int, + modifier: Modifier = Modifier, +) { + val indicatorHeight by remember { + derivedStateOf { + when (pinsCount) { + 0 -> 0 + 1 -> 32 + 2 -> 18 + else -> 11 + } + } + } + val lazyListState = rememberLazyListState() + LaunchedEffect(pinIndex) { + val viewportSize = lazyListState.layoutInfo.viewportSize + lazyListState.animateScrollToItem( + pinIndex, + (indicatorHeight / 2 - viewportSize.height / 2) + ) + } + LazyColumn( + modifier = modifier, + state = lazyListState, + verticalArrangement = spacedBy(2.dp), + userScrollEnabled = false + ) { + items(pinsCount) { index -> + Box( + modifier = Modifier + .width(2.dp) + .height(indicatorHeight.dp) + .background( + color = if (index == pinIndex) { + ElementTheme.colors.iconAccentPrimary + } else { + ElementTheme.colors.pinnedMessageBannerIndicator + } + ) + ) + } + } +} + +@Composable +private fun PinnedMessageItem( + index: Int, + totalCount: Int, + message: String, + modifier: Modifier = Modifier, +) { + val countMessage = "${index + 1} of $totalCount" + val fullMessage = "$countMessage Pinned messages" + Column(modifier = modifier) { + if (totalCount > 1) { + Text( + text = annotatedTextWithBold( + text = fullMessage, + boldText = countMessage, + ), + style = ElementTheme.typography.fontBodySmMedium, + color = ElementTheme.colors.textActionAccent, + maxLines = 1, + ) + } + Text( + text = message, + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textPrimary, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + ) + + } +} + +@PreviewsDayNight +@Composable +fun PinnedMessagesBannerViewPreview(@PreviewParameter(PinnedMessagesBannerStateProvider::class) state: PinnedMessagesBannerState) = ElementPreview { + PinnedMessagesBannerView( + state = state + ) +} 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 2d08b8d4a2..bc8daf2b00 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 @@ -30,6 +30,7 @@ import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactory import io.element.android.features.messages.impl.messagecomposer.DefaultMessageComposerContext import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter +import io.element.android.features.messages.impl.pinned.banner.aPinnedMessagesBannerState import io.element.android.features.messages.impl.textcomposer.TestRichTextEditorStateFactory import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.timeline.TimelineItemIndexer @@ -56,6 +57,7 @@ import io.element.android.features.poll.test.actions.FakeEndPollAction import io.element.android.features.poll.test.actions.FakeSendPollResponseAction import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -828,6 +830,7 @@ class MessagesPresenterTest { val readReceiptBottomSheetPresenter = ReadReceiptBottomSheetPresenter() val customReactionPresenter = CustomReactionPresenter(emojibaseProvider = FakeEmojibaseProvider()) val reactionSummaryPresenter = ReactionSummaryPresenter(room = matrixRoom) + return MessagesPresenter( room = matrixRoom, composerPresenter = messageComposerPresenter, @@ -838,6 +841,7 @@ class MessagesPresenterTest { customReactionPresenter = customReactionPresenter, reactionSummaryPresenter = reactionSummaryPresenter, readReceiptBottomSheetPresenter = readReceiptBottomSheetPresenter, + pinnedMessagesBannerPresenter = { aPinnedMessagesBannerState() }, networkMonitor = FakeNetworkMonitor(), snackbarDispatcher = SnackbarDispatcher(), navigator = navigator, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt index 5fc6fd2a23..4603541055 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt @@ -179,6 +179,14 @@ val SemanticColors.badgeNegativeBackgroundColor val SemanticColors.badgeNegativeContentColor get() = if (isLight) LightColorTokens.colorRed1100 else DarkColorTokens.colorRed1100 +@OptIn(CoreColorToken::class) +val SemanticColors.pinnedMessageBannerIndicator + get() = if (isLight) LightColorTokens.colorAlphaGray600 else DarkColorTokens.colorAlphaGray600 + +@OptIn(CoreColorToken::class) +val SemanticColors.pinnedMessageBannerBorder + get() = if (isLight) LightColorTokens.colorAlphaGray400 else DarkColorTokens.colorAlphaGray400 + @PreviewsDayNight @Composable internal fun ColorAliasesPreview() = ElementPreview { From aebcc52309ca0a1f044419788737daa376322eb6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 23 Jul 2024 21:17:35 +0200 Subject: [PATCH 008/186] Join Room : makes sure we can join by alias --- .../response/AcceptDeclineInvitePresenter.kt | 3 +- .../AcceptDeclineInvitePresenterTest.kt | 14 +++-- .../joinroom/impl/JoinRoomPresenter.kt | 4 +- .../joinroom/impl/JoinRoomPresenterTest.kt | 13 ++-- .../libraries/matrix/api/MatrixClient.kt | 8 ++- .../matrix/api/room/join/JoinRoom.kt | 4 +- .../matrix/api/roomlist/RoomSummary.kt | 3 + .../libraries/matrix/impl/RustMatrixClient.kt | 53 +++++++++------- .../matrix/impl/room/join/DefaultJoinRoom.kt | 33 ++++++---- .../roomlist/RoomSummaryDetailsFactory.kt | 1 + .../impl/room/join/DefaultJoinRoomTest.kt | 60 ++++++++++++++++--- .../libraries/matrix/test/FakeMatrixClient.kt | 22 +++---- .../matrix/test/room/RoomSummaryFixture.kt | 2 + .../matrix/test/room/join/FakeJoinRoom.kt | 8 +-- .../components/RoomSummaryDetailsProvider.kt | 2 + ...otificationBroadcastReceiverHandlerTest.kt | 5 +- 16 files changed, 158 insertions(+), 77 deletions(-) diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt index 73a82a71f5..95bebc07e6 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt @@ -33,6 +33,7 @@ import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.architecture.runUpdatingState 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.toRoomIdOrAlias import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.push.api.notifications.NotificationCleaner import kotlinx.coroutines.CoroutineScope @@ -107,7 +108,7 @@ class AcceptDeclineInvitePresenter @Inject constructor( ) = launch { acceptedAction.runUpdatingState { joinRoom( - roomId = roomId, + roomIdOrAlias = roomId.toRoomIdOrAlias(), serverNames = emptyList(), trigger = JoinedRoom.Trigger.Invite, ) diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt index 39a0321b01..239ac9c597 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt @@ -23,7 +23,9 @@ import io.element.android.features.invite.api.response.InviteData import io.element.android.libraries.architecture.AsyncAction 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.RoomIdOrAlias import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_SESSION_ID @@ -178,8 +180,8 @@ class AcceptDeclineInvitePresenterTest { @Test fun `present - accepting invite error flow`() = runTest { - val joinRoomFailure = lambdaRecorder { roomId: RoomId, _: List, _: JoinedRoom.Trigger -> - Result.failure(RuntimeException("Failed to join room $roomId")) + val joinRoomFailure = lambdaRecorder { roomIdOrAlias: RoomIdOrAlias, _: List, _: JoinedRoom.Trigger -> + Result.failure(RuntimeException("Failed to join room $roomIdOrAlias")) } val presenter = createAcceptDeclineInvitePresenter(joinRoomLambda = joinRoomFailure) presenter.test { @@ -208,7 +210,7 @@ class AcceptDeclineInvitePresenterTest { assert(joinRoomFailure) .isCalledOnce() .with( - value(A_ROOM_ID), + value(A_ROOM_ID.toRoomIdOrAlias()), value(emptyList()), value(JoinedRoom.Trigger.Invite) ) @@ -222,7 +224,7 @@ class AcceptDeclineInvitePresenterTest { val fakeNotificationCleaner = FakeNotificationCleaner( clearMembershipNotificationForRoomLambda = clearMembershipNotificationForRoomLambda ) - val joinRoomSuccess = lambdaRecorder { _: RoomId, _: List, _: JoinedRoom.Trigger -> + val joinRoomSuccess = lambdaRecorder { _: RoomIdOrAlias, _: List, _: JoinedRoom.Trigger -> Result.success(Unit) } val presenter = createAcceptDeclineInvitePresenter( @@ -248,7 +250,7 @@ class AcceptDeclineInvitePresenterTest { assert(joinRoomSuccess) .isCalledOnce() .with( - value(A_ROOM_ID), + value(A_ROOM_ID.toRoomIdOrAlias()), value(emptyList()), value(JoinedRoom.Trigger.Invite) ) @@ -271,7 +273,7 @@ class AcceptDeclineInvitePresenterTest { private fun createAcceptDeclineInvitePresenter( client: MatrixClient = FakeMatrixClient(), - joinRoomLambda: (RoomId, List, JoinedRoom.Trigger) -> Result = { _, _, _ -> + joinRoomLambda: (RoomIdOrAlias, List, JoinedRoom.Trigger) -> Result = { _, _, _ -> Result.success(Unit) }, notificationCleaner: NotificationCleaner = FakeNotificationCleaner(), diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt index bba2a82a34..3fb4659c96 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt @@ -96,7 +96,7 @@ class JoinRoomPresenter @AssistedInject constructor( } else -> { value = ContentState.Loading(roomIdOrAlias) - val result = matrixClient.getRoomPreviewFromRoomId(roomId, serverNames) + val result = matrixClient.getRoomPreview(roomIdOrAlias, serverNames) value = result.fold( onSuccess = { roomPreview -> roomPreview.toContentState() @@ -153,7 +153,7 @@ class JoinRoomPresenter @AssistedInject constructor( private fun CoroutineScope.joinRoom(joinAction: MutableState>) = launch { joinAction.runUpdatingState { joinRoom.invoke( - roomId = roomId, + roomIdOrAlias = roomIdOrAlias, serverNames = serverNames, trigger = trigger ) diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt index 7a6e08244c..b636e1497c 100644 --- a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt @@ -29,6 +29,7 @@ import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.api.room.CurrentUserMembership @@ -180,7 +181,7 @@ class JoinRoomPresenterTest { @Test fun `present - when room is joined with success, all the parameters are provided`() = runTest { val aTrigger = JoinedRoom.Trigger.MobilePermalink - val joinRoomLambda = lambdaRecorder { _: RoomId, _: List, _: JoinedRoom.Trigger -> + val joinRoomLambda = lambdaRecorder { _: RoomIdOrAlias, _: List, _: JoinedRoom.Trigger -> Result.success(Unit) } val presenter = createJoinRoomPresenter( @@ -201,7 +202,7 @@ class JoinRoomPresenterTest { } joinRoomLambda.assertions() .isCalledOnce() - .with(value(A_ROOM_ID), value(A_SERVER_LIST), value(aTrigger)) + .with(value(A_ROOM_ID.toRoomIdOrAlias()), value(A_SERVER_LIST), value(aTrigger)) } } @@ -366,7 +367,7 @@ class JoinRoomPresenterTest { @Test fun `present - when room is not known RoomPreview is loaded`() = runTest { val client = FakeMatrixClient( - getRoomPreviewFromRoomIdResult = { _, _ -> + getRoomPreviewResult = { _, _ -> Result.success( RoomPreview( roomId = A_ROOM_ID, @@ -411,7 +412,7 @@ class JoinRoomPresenterTest { @Test fun `present - when room is not known RoomPreview is loaded with error`() = runTest { val client = FakeMatrixClient( - getRoomPreviewFromRoomIdResult = { _, _ -> + getRoomPreviewResult = { _, _ -> Result.failure(AN_EXCEPTION) } ) @@ -449,7 +450,7 @@ class JoinRoomPresenterTest { @Test fun `present - when room is not known RoomPreview is loaded with error 403`() = runTest { val client = FakeMatrixClient( - getRoomPreviewFromRoomIdResult = { _, _ -> + getRoomPreviewResult = { _, _ -> Result.failure(Exception("403")) } ) @@ -474,7 +475,7 @@ class JoinRoomPresenterTest { serverNames: List = emptyList(), trigger: JoinedRoom.Trigger = JoinedRoom.Trigger.Invite, matrixClient: MatrixClient = FakeMatrixClient(), - joinRoomLambda: (RoomId, List, JoinedRoom.Trigger) -> Result = { _, _, _ -> + joinRoomLambda: (RoomIdOrAlias, List, JoinedRoom.Trigger) -> Result = { _, _, _ -> Result.success(Unit) }, knockRoom: KnockRoom = FakeKnockRoom(), 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 b3b47d4499..3209d49e03 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 @@ -19,6 +19,7 @@ package io.element.android.libraries.matrix.api import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias 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.createroom.CreateRoomParameters @@ -35,6 +36,7 @@ import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias import io.element.android.libraries.matrix.api.room.preview.RoomPreview import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService import io.element.android.libraries.matrix.api.roomlist.RoomListService +import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser @@ -65,8 +67,8 @@ interface MatrixClient : Closeable { suspend fun setDisplayName(displayName: String): Result suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result suspend fun removeAvatar(): Result - suspend fun joinRoom(roomId: RoomId): Result - suspend fun joinRoomByIdOrAlias(roomId: RoomId, serverNames: List): Result + suspend fun joinRoom(roomId: RoomId): Result + suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result suspend fun knockRoom(roomId: RoomId): Result fun syncService(): SyncService fun sessionVerificationService(): SessionVerificationService @@ -104,7 +106,6 @@ interface MatrixClient : Closeable { suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result suspend fun getRecentlyVisitedRooms(): Result> suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result - suspend fun getRoomPreviewFromRoomId(roomId: RoomId, serverNames: List): Result /** * Enables or disables the sending queue, according to the given parameter. @@ -132,4 +133,5 @@ interface MatrixClient : Closeable { * Execute generic GET requests through the SDKs internal HTTP client. */ suspend fun getUrl(url: String): Result + suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/join/JoinRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/join/JoinRoom.kt index fe6a2d9e47..87cc76e199 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/join/JoinRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/join/JoinRoom.kt @@ -17,11 +17,11 @@ package io.element.android.libraries.matrix.api.room.join import im.vector.app.features.analytics.plan.JoinedRoom -import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias interface JoinRoom { suspend operator fun invoke( - roomId: RoomId, + roomIdOrAlias: RoomIdOrAlias, serverNames: List, trigger: JoinedRoom.Trigger, ): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt index 6841af9721..b932b235fa 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt @@ -28,6 +28,7 @@ data class RoomSummary( val roomId: RoomId, val name: String?, val canonicalAlias: RoomAlias?, + val alternativeAliases: List, val isDirect: Boolean, val avatarUrl: String?, val lastMessage: RoomMessage?, @@ -44,4 +45,6 @@ data class RoomSummary( val heroes: List, ) { val lastMessageTimestamp = lastMessage?.originServerTs + val aliases: List + get() = listOfNotNull(canonicalAlias) + alternativeAliases } 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 db86e1a2a5..3aab5bebed 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 @@ -24,7 +24,9 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters import io.element.android.libraries.matrix.api.createroom.RoomPreset import io.element.android.libraries.matrix.api.createroom.RoomVisibility @@ -41,6 +43,7 @@ import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias import io.element.android.libraries.matrix.api.room.preview.RoomPreview import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService import io.element.android.libraries.matrix.api.roomlist.RoomListService +import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.sync.SyncState import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults @@ -175,7 +178,7 @@ class RustMatrixClient( val (anonymizedAccessToken, anonymizedRefreshToken) = existingData.anonymizedTokens() clientLog.d( "Removing session data with access token '$anonymizedAccessToken' " + - "and refresh token '$anonymizedRefreshToken'." + "and refresh token '$anonymizedRefreshToken'." ) if (existingData != null) { // Set isTokenValid to false @@ -320,16 +323,23 @@ class RustMatrixClient( /** * Wait for the room to be available in the room list. - * @param roomId the room id to wait for + * @param roomIdOrAlias the room id or alias to wait for * @param timeout the timeout to wait for the room to be available * @throws TimeoutCancellationException if the room is not available after the timeout */ - private suspend fun awaitRoom(roomId: RoomId, timeout: Duration) { - withTimeout(timeout) { + private suspend fun awaitRoom(roomIdOrAlias: RoomIdOrAlias, timeout: Duration): RoomSummary { + val predicate: (List) -> Boolean = when (roomIdOrAlias) { + is RoomIdOrAlias.Alias -> { roomSummaries: List -> + roomSummaries.flatMap { it.aliases }.contains(roomIdOrAlias.roomAlias) + } + is RoomIdOrAlias.Id -> { roomSummaries: List -> + roomSummaries.map { it.roomId }.contains(roomIdOrAlias.roomId) + } + } + return withTimeout(timeout) { roomListService.allRooms.summaries - .filter { roomSummaries -> - roomSummaries.map { it.roomId }.contains(roomId) - } + .filter(predicate) + .first() .first() } } @@ -373,7 +383,7 @@ class RustMatrixClient( val roomId = RoomId(client.createRoom(rustParams)) // Wait to receive the room back from the sync but do not returns failure if it fails. try { - awaitRoom(roomId, 30.seconds) + awaitRoom(roomId.toRoomIdOrAlias(), 30.seconds) } catch (e: Exception) { Timber.e(e, "Timeout waiting for the room to be available in the room list") } @@ -424,30 +434,29 @@ class RustMatrixClient( runCatching { client.removeAvatar() } } - override suspend fun joinRoom(roomId: RoomId): Result = withContext(sessionDispatcher) { + override suspend fun joinRoom(roomId: RoomId): Result = withContext(sessionDispatcher) { runCatching { client.joinRoomById(roomId.value).destroy() try { - awaitRoom(roomId, 10.seconds) + awaitRoom(roomId.toRoomIdOrAlias(), 10.seconds) } catch (e: Exception) { Timber.e(e, "Timeout waiting for the room to be available in the room list") + null } } } - override suspend fun joinRoomByIdOrAlias( - roomId: RoomId, - serverNames: List, - ): Result = withContext(sessionDispatcher) { + override suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result = withContext(sessionDispatcher) { runCatching { client.joinRoomByIdOrAlias( - roomIdOrAlias = roomId.value, + roomIdOrAlias = roomIdOrAlias.identifier, serverNames = serverNames, ).destroy() try { - awaitRoom(roomId, 10.seconds) + awaitRoom(roomIdOrAlias, 10.seconds) } catch (e: Exception) { Timber.e(e, "Timeout waiting for the room to be available in the room list") + null } } } @@ -478,12 +487,12 @@ class RustMatrixClient( } } - override suspend fun getRoomPreviewFromRoomId(roomId: RoomId, serverNames: List): Result = withContext(sessionDispatcher) { + override suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result = withContext(sessionDispatcher) { runCatching { - client.getRoomPreviewFromRoomId( - roomId = roomId.value, - viaServers = serverNames, - ).let(RoomPreviewMapper::map) + when (roomIdOrAlias) { + is RoomIdOrAlias.Alias -> client.getRoomPreviewFromRoomAlias(roomIdOrAlias.roomAlias.value) + is RoomIdOrAlias.Id -> client.getRoomPreviewFromRoomId(roomIdOrAlias.roomId.value, serverNames) + }.let(RoomPreviewMapper::map) } } @@ -581,7 +590,7 @@ class RustMatrixClient( var room = getRoom(roomId) if (room == null) { emit(Optional.empty()) - awaitRoom(roomId, INFINITE) + awaitRoom(roomId.toRoomIdOrAlias(), INFINITE) room = getRoom(roomId) } room?.use { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/join/DefaultJoinRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/join/DefaultJoinRoom.kt index d2ce4e61d5..063facbc96 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/join/DefaultJoinRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/join/DefaultJoinRoom.kt @@ -20,8 +20,9 @@ import com.squareup.anvil.annotations.ContributesBinding import im.vector.app.features.analytics.plan.JoinedRoom import io.element.android.libraries.di.SessionScope 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.RoomIdOrAlias import io.element.android.libraries.matrix.api.room.join.JoinRoom +import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.impl.analytics.toAnalyticsJoinedRoom import io.element.android.services.analytics.api.AnalyticsService import javax.inject.Inject @@ -32,18 +33,30 @@ class DefaultJoinRoom @Inject constructor( private val analyticsService: AnalyticsService, ) : JoinRoom { override suspend fun invoke( - roomId: RoomId, + roomIdOrAlias: RoomIdOrAlias, serverNames: List, - trigger: JoinedRoom.Trigger, + trigger: JoinedRoom.Trigger ): Result { - return if (serverNames.isEmpty()) { - client.joinRoom(roomId) - } else { - client.joinRoomByIdOrAlias(roomId, serverNames) - }.onSuccess { - client.getRoom(roomId)?.use { room -> - analyticsService.capture(room.toAnalyticsJoinedRoom(trigger)) + return when (roomIdOrAlias) { + is RoomIdOrAlias.Id -> { + if (serverNames.isEmpty()) { + client.joinRoom(roomIdOrAlias.roomId) + } else { + client.joinRoomByIdOrAlias(roomIdOrAlias, serverNames) + } } + is RoomIdOrAlias.Alias -> { + client.joinRoomByIdOrAlias(roomIdOrAlias, serverNames = emptyList()) + } + }.onSuccess { roomSummary -> + client.captureJoinedRoomAnalytics(roomSummary, trigger) + }.map { } + } + + private suspend fun MatrixClient.captureJoinedRoomAnalytics(roomSummary: RoomSummary?, trigger: JoinedRoom.Trigger) { + if (roomSummary == null) return + getRoom(roomSummary.roomId)?.use { room -> + analyticsService.capture(room.toAnalyticsJoinedRoom(trigger)) } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt index a833734a5c..9c67eb1221 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt @@ -38,6 +38,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto roomId = RoomId(roomInfo.id), name = roomInfo.displayName, canonicalAlias = roomInfo.canonicalAlias?.let(::RoomAlias), + alternativeAliases = roomInfo.alternativeAliases.map(::RoomAlias), isDirect = roomInfo.isDirect, avatarUrl = roomInfo.avatarUrl, numUnreadMentions = roomInfo.numUnreadMentions.toInt(), 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 6296f219de..9941b6b1ed 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 @@ -20,11 +20,15 @@ import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.JoinedRoom 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.RoomIdOrAlias +import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.impl.analytics.toAnalyticsJoinedRoom +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SERVER_LIST import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -33,9 +37,10 @@ import org.junit.Test class DefaultJoinRoomTest { @Test - fun `when there is no server names, the classic join room API is used`() = runTest { - val joinRoomLambda = lambdaRecorder { _: RoomId -> Result.success(Unit) } - val joinRoomByIdOrAliasLambda = lambdaRecorder { _: RoomId, _: List -> Result.success(Unit) } + fun `when using roomId and there is no server names, the classic join room API is used`() = runTest { + val roomSummary = aRoomSummaryFilled() + val joinRoomLambda = lambdaRecorder { _: RoomId -> Result.success(roomSummary) } + val joinRoomByIdOrAliasLambda = lambdaRecorder { _: RoomIdOrAlias, _: List -> Result.success(roomSummary) } val roomResult = FakeMatrixRoom() val aTrigger = JoinedRoom.Trigger.MobilePermalink val client: MatrixClient = FakeMatrixClient().also { @@ -51,7 +56,7 @@ class DefaultJoinRoomTest { client = client, analyticsService = analyticsService, ) - sut.invoke(A_ROOM_ID, emptyList(), aTrigger) + sut.invoke(A_ROOM_ID.toRoomIdOrAlias(), emptyList(), aTrigger) joinRoomByIdOrAliasLambda .assertions() .isNeverCalled() @@ -67,9 +72,10 @@ class DefaultJoinRoomTest { } @Test - fun `when server names are available, joinRoomByIdOrAlias API is used`() = runTest { - val joinRoomLambda = lambdaRecorder { _: RoomId -> Result.success(Unit) } - val joinRoomByIdOrAliasLambda = lambdaRecorder { _: RoomId, _: List -> Result.success(Unit) } + fun `when using roomId and server names are available, joinRoomByIdOrAlias API is used`() = runTest { + val roomSummary = aRoomSummaryFilled() + val joinRoomLambda = lambdaRecorder { _: RoomId -> Result.success(roomSummary) } + val joinRoomByIdOrAliasLambda = lambdaRecorder { _: RoomIdOrAlias, _: List -> Result.success(roomSummary) } val roomResult = FakeMatrixRoom() val aTrigger = JoinedRoom.Trigger.MobilePermalink val client: MatrixClient = FakeMatrixClient().also { @@ -85,12 +91,12 @@ class DefaultJoinRoomTest { client = client, analyticsService = analyticsService, ) - sut.invoke(A_ROOM_ID, A_SERVER_LIST, aTrigger) + sut.invoke(A_ROOM_ID.toRoomIdOrAlias(), A_SERVER_LIST, aTrigger) joinRoomByIdOrAliasLambda .assertions() .isCalledOnce() .with( - value(A_ROOM_ID), + value(A_ROOM_ID.toRoomIdOrAlias()), value(A_SERVER_LIST) ) joinRoomLambda @@ -100,4 +106,40 @@ class DefaultJoinRoomTest { roomResult.toAnalyticsJoinedRoom(aTrigger) ) } + + @Test + fun `when using roomAlias, joinRoomByIdOrAlias API is used`() = runTest { + val roomSummary = aRoomSummaryFilled() + val joinRoomLambda = lambdaRecorder { _: RoomId -> Result.success(roomSummary) } + val joinRoomByIdOrAliasLambda = lambdaRecorder { _: RoomIdOrAlias, _: List -> Result.success(roomSummary) } + val roomResult = FakeMatrixRoom() + val aTrigger = JoinedRoom.Trigger.MobilePermalink + val client: MatrixClient = FakeMatrixClient().also { + it.joinRoomLambda = joinRoomLambda + it.joinRoomByIdOrAliasLambda = joinRoomByIdOrAliasLambda + it.givenGetRoomResult( + roomId = A_ROOM_ID, + result = roomResult + ) + } + val analyticsService = FakeAnalyticsService() + val sut = DefaultJoinRoom( + client = client, + analyticsService = analyticsService, + ) + sut.invoke(A_ROOM_ALIAS.toRoomIdOrAlias(), A_SERVER_LIST, aTrigger) + joinRoomByIdOrAliasLambda + .assertions() + .isCalledOnce() + .with( + value(A_ROOM_ALIAS.toRoomIdOrAlias()), + value(emptyList()) + ) + joinRoomLambda + .assertions() + .isNeverCalled() + assertThat(analyticsService.capturedEvents).containsExactly( + roomResult.toAnalyticsJoinedRoom(aTrigger) + ) + } } 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 1b6223279c..1fb8878488 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 @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias 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.createroom.CreateRoomParameters @@ -36,6 +37,7 @@ import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias import io.element.android.libraries.matrix.api.room.preview.RoomPreview import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService import io.element.android.libraries.matrix.api.roomlist.RoomListService +import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService @@ -80,7 +82,7 @@ class FakeMatrixClient( private val roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService(), private val accountManagementUrlString: Result = Result.success(null), private val resolveRoomAliasResult: (RoomAlias) -> Result = { Result.success(ResolvedRoomAlias(A_ROOM_ID, emptyList())) }, - private val getRoomPreviewFromRoomIdResult: (RoomId, List) -> Result = { _, _ -> Result.failure(AN_EXCEPTION) }, + private val getRoomPreviewResult: (RoomIdOrAlias, List) -> Result = { _, _ -> Result.failure(AN_EXCEPTION) }, private val clearCacheLambda: () -> Unit = { lambdaError() }, private val userIdServerNameLambda: () -> String = { lambdaError() }, private val getUrlLambda: (String) -> Result = { lambdaError() }, @@ -108,11 +110,11 @@ class FakeMatrixClient( private var setDisplayNameResult: Result = Result.success(Unit) private var uploadAvatarResult: Result = Result.success(Unit) private var removeAvatarResult: Result = Result.success(Unit) - var joinRoomLambda: (RoomId) -> Result = { - Result.success(Unit) + var joinRoomLambda: (RoomId) -> Result = { + Result.success(null) } - var joinRoomByIdOrAliasLambda: (RoomId, List) -> Result = { _, _ -> - Result.success(Unit) + var joinRoomByIdOrAliasLambda: (RoomIdOrAlias, List) -> Result = { _, _ -> + Result.success(null) } var knockRoomLambda: (RoomId) -> Result = { Result.success(Unit) @@ -207,10 +209,10 @@ class FakeMatrixClient( return removeAvatarResult } - override suspend fun joinRoom(roomId: RoomId): Result = joinRoomLambda(roomId) + override suspend fun joinRoom(roomId: RoomId): Result = joinRoomLambda(roomId) - override suspend fun joinRoomByIdOrAlias(roomId: RoomId, serverNames: List): Result { - return joinRoomByIdOrAliasLambda(roomId, serverNames) + override suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result { + return joinRoomByIdOrAliasLambda(roomIdOrAlias, serverNames) } override suspend fun knockRoom(roomId: RoomId): Result = knockRoomLambda(roomId) @@ -297,8 +299,8 @@ class FakeMatrixClient( resolveRoomAliasResult(roomAlias) } - override suspend fun getRoomPreviewFromRoomId(roomId: RoomId, serverNames: List) = simulateLongTask { - getRoomPreviewFromRoomIdResult(roomId, serverNames) + override suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result = simulateLongTask { + getRoomPreviewResult(roomIdOrAlias, serverNames) } override suspend fun getRecentlyVisitedRooms(): Result> { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt index f5ef3faa0b..f83379a70e 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt @@ -68,6 +68,7 @@ fun aRoomSummary( notificationMode: RoomNotificationMode? = null, inviter: RoomMember? = null, canonicalAlias: RoomAlias? = null, + alternativeAliases: List = emptyList(), hasRoomCall: Boolean = false, isDm: Boolean = false, isFavorite: Boolean = false, @@ -86,6 +87,7 @@ fun aRoomSummary( userDefinedNotificationMode = notificationMode, inviter = inviter, canonicalAlias = canonicalAlias, + alternativeAliases = alternativeAliases, hasRoomCall = hasRoomCall, isDm = isDm, isFavorite = isFavorite, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/join/FakeJoinRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/join/FakeJoinRoom.kt index 55eade69d4..830d02f741 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/join/FakeJoinRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/join/FakeJoinRoom.kt @@ -17,18 +17,18 @@ package io.element.android.libraries.matrix.test.room.join import im.vector.app.features.analytics.plan.JoinedRoom -import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.tests.testutils.simulateLongTask class FakeJoinRoom( - var lambda: (RoomId, List, JoinedRoom.Trigger) -> Result + var lambda: (RoomIdOrAlias, List, JoinedRoom.Trigger) -> Result ) : JoinRoom { override suspend fun invoke( - roomId: RoomId, + roomIdOrAlias: RoomIdOrAlias, serverNames: List, trigger: JoinedRoom.Trigger, ): Result = simulateLongTask { - lambda(roomId, serverNames, trigger) + lambda(roomIdOrAlias, serverNames, trigger) } } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/RoomSummaryDetailsProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/RoomSummaryDetailsProvider.kt index c5e117808b..7454ec30bb 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/RoomSummaryDetailsProvider.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/RoomSummaryDetailsProvider.kt @@ -38,6 +38,7 @@ fun aRoomSummaryDetails( roomId: RoomId = RoomId("!room:domain"), name: String? = "roomName", canonicalAlias: RoomAlias? = null, + alternativeAliases: List = emptyList(), isDirect: Boolean = true, avatarUrl: String? = null, lastMessage: RoomMessage? = null, @@ -56,6 +57,7 @@ fun aRoomSummaryDetails( roomId = roomId, name = name, canonicalAlias = canonicalAlias, + alternativeAliases = alternativeAliases, isDirect = isDirect, avatarUrl = avatarUrl, lastMessage = lastMessage, diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt index f4dedfad97..40d32878df 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt @@ -25,6 +25,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.asEventId import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_MESSAGE @@ -261,7 +262,7 @@ class NotificationBroadcastReceiverHandlerTest { @Test fun `Test join room`() = runTest { - val joinRoom = lambdaRecorder> { _ -> Result.success(Unit) } + val joinRoom = lambdaRecorder> { _ -> Result.success(null) } val clearMembershipNotificationForRoomLambda = lambdaRecorder { _, _ -> } val fakeNotificationCleaner = FakeNotificationCleaner( clearMembershipNotificationForRoomLambda = clearMembershipNotificationForRoomLambda, @@ -444,7 +445,7 @@ class NotificationBroadcastReceiverHandlerTest { private fun TestScope.createNotificationBroadcastReceiverHandler( matrixRoom: FakeMatrixRoom? = FakeMatrixRoom(), - joinRoom: (RoomId) -> Result = { lambdaError() }, + joinRoom: (RoomId) -> Result = { lambdaError() }, matrixClient: MatrixClient? = FakeMatrixClient().apply { givenGetRoomResult(A_ROOM_ID, matrixRoom) joinRoomLambda = joinRoom From 0dd8303467053f71a42fd1680c33925eb2b2cc20 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 24 Jul 2024 10:33:06 +0200 Subject: [PATCH 009/186] Join Room : fallback to show Join button when RoomContent is Unknown (preview fails) --- .../element/android/features/joinroom/impl/JoinRoomState.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt index ab66d0d80c..f71ece39af 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -37,7 +37,11 @@ data class JoinRoomState( val eventSink: (JoinRoomEvents) -> Unit ) { val joinAuthorisationStatus = when (contentState) { + // Use the join authorisation status from the loaded content state is ContentState.Loaded -> contentState.joinAuthorisationStatus + // Assume that if the room is unknown, the user can join it + is ContentState.UnknownRoom -> JoinAuthorisationStatus.CanJoin + // Otherwise assume that the user can't join the room else -> JoinAuthorisationStatus.Unknown } } From 5302d8bd0efb6ba8dbe24e1bb27a97158367835b Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 24 Jul 2024 14:38:34 +0200 Subject: [PATCH 010/186] version++ --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 9fb6df696a..e5df6fe90c 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -56,7 +56,7 @@ private const val versionMinor = 5 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -private const val versionPatch = 0 +private const val versionPatch = 1 object Versions { val versionCode = 4_000_000 + versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch From 947480f229a94e5ae3e7af36c9864ad2b3b0fb38 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 24 Jul 2024 16:29:08 +0200 Subject: [PATCH 011/186] Changelog for version 0.5.0 --- CHANGES.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index c2c2641b34..2661597461 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,80 @@ +Changes in Element X v0.5.0 (2024-07-24) +========================================= + +### 🙌 Improvements +* Add icon for "Mark as read" and "Mark as unread" actions. by @bmarty in https://github.com/element-hq/element-x-android/pull/3144 +* Add support for Picture In Picture for Element Call by @bmarty in https://github.com/element-hq/element-x-android/pull/3159 +* Set pin grace period to 2 minutes by @bmarty in https://github.com/element-hq/element-x-android/pull/3172 +* Unify the way we decide whether a room is a DM or a group room by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3100 +* Subscribe to `RoomListItems` in the visible range by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3169 +* Improve pip and add feature flag. by @bmarty in https://github.com/element-hq/element-x-android/pull/3199 +* Open Source licenses: add color for links. by @bmarty in https://github.com/element-hq/element-x-android/pull/3215 +* Cancel ringing call notification on call cancellation by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3047 + +### 🐛 Bugfixes +* Fix `MainActionButton` layout for long texts by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3158 +* Always follow the desired theme for Pin, Incoming Call and Element Call screens by @bmarty in https://github.com/element-hq/element-x-android/pull/3165 +* Fix empty screen issue after clearing the cache by @bmarty in https://github.com/element-hq/element-x-android/pull/3163 +* Restore intentional mentions in the markdown/plain text editor by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3193 +* Fix crash in the room list after a forced log out in background by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3180 +* Clear existing notification when a room is marked as read by @bmarty in https://github.com/element-hq/element-x-android/pull/3203 +* Fix crash when Pin code screen is displayed by @bmarty in https://github.com/element-hq/element-x-android/pull/3205 +* Fix pillification not working for non formatted message bodies by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3201 +* Update grammar on Matrix Ids to be more spec compliant and render error instead of infinite loading in room member list screen by @bmarty in https://github.com/element-hq/element-x-android/pull/3206 +* Reduce the risk of text truncation in buttons. by @bmarty in https://github.com/element-hq/element-x-android/pull/3209 +* Ensure that the manual dark theme is rendering correctly regarding -night resource and keyboard by @bmarty in https://github.com/element-hq/element-x-android/pull/3216 +* Fix rendering issue of SunsetPage in dark mode by @bmarty in https://github.com/element-hq/element-x-android/pull/3217 +* Fix linkification not working for `Spanned` strings in text messages by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3233 +* Edit : fallback to room.edit when timeline item is not found. by @ganfra in https://github.com/element-hq/element-x-android/pull/3239 + +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3156 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3192 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3232 + +### 🧱 Build +* Remove Showkase processor not found warning from Danger by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3148 +* Set targetSDK to 34 by @bmarty in https://github.com/element-hq/element-x-android/pull/3149 +* Add a local copy of `inplace-fix.py` and `fix-pg-map-id.py` by @bmarty in https://github.com/element-hq/element-x-android/pull/3167 +* Only add private SSH keys and clone submodules in the original repo by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3225 +* Fix CI for forks by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3226 + +### Dependency upgrades +* Update dependency io.element.android:compound-android to v0.0.7 by @renovate in https://github.com/element-hq/element-x-android/pull/3143 +* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.31 by @renovate in https://github.com/element-hq/element-x-android/pull/3145 +* Update dependency com.squareup:kotlinpoet to v1.18.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3150 +* Update dependency org.robolectric:robolectric to v4.13 by @renovate in https://github.com/element-hq/element-x-android/pull/3157 +* Update plugin dependencycheck to v10.0.2 by @renovate in https://github.com/element-hq/element-x-android/pull/3154 +* Update wysiwyg to v2.37.5 by @renovate in https://github.com/element-hq/element-x-android/pull/3162 +* Update plugin sonarqube to v5.1.0.4882 by @renovate in https://github.com/element-hq/element-x-android/pull/3139 +* Update dependency org.jsoup:jsoup to v1.18.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3171 +* Update dependency com.google.firebase:firebase-bom to v33.1.2 by @renovate in https://github.com/element-hq/element-x-android/pull/3178 +* Update telephoto to v0.12.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3191 +* Update dependency com.google.truth:truth to v1.4.4 by @renovate in https://github.com/element-hq/element-x-android/pull/3187 +* Update dependency com.squareup:kotlinpoet to v1.18.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3194 +* Update dependency io.mockk:mockk to v1.13.12 by @renovate in https://github.com/element-hq/element-x-android/pull/3198 +* Update dependency io.sentry:sentry-android to v7.12.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3200 +* Update plugin dependencycheck to v10.0.3 by @renovate in https://github.com/element-hq/element-x-android/pull/3204 +* Update dependency gradle to v8.9 by @renovate in https://github.com/element-hq/element-x-android/pull/3177 +* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.32 by @renovate in https://github.com/element-hq/element-x-android/pull/3202 +* Update coil to v2.7.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3210 +* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.33 by @renovate in https://github.com/element-hq/element-x-android/pull/3220 +* Update wysiwyg to v2.37.7 by @renovate in https://github.com/element-hq/element-x-android/pull/3218 +* Update telephoto to v0.12.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3230 +* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.34 by @renovate in https://github.com/element-hq/element-x-android/pull/3237 + +### Others +* Reduce delay when selecting room list filters by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3160 +* Add `--alignment-preserved true` when signing APK for F-Droid. by @bmarty in https://github.com/element-hq/element-x-android/pull/3161 +* Ensure that all callback plugins are invoked. by @bmarty in https://github.com/element-hq/element-x-android/pull/3146 +* Add generated screen to show open source licenses in Gplay variant by @bmarty in https://github.com/element-hq/element-x-android/pull/3207 +* Performance : improve time to open a room. by @ganfra in https://github.com/element-hq/element-x-android/pull/3186 +* Add logging to help debug forced logout issues by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3208 +* Use the right filename for log files so they're sorted in rageshakes by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3219 +* Compose : add immutability to some Reaction classes by @ganfra in https://github.com/element-hq/element-x-android/pull/3224 +* Fix stickers display text on room summary by @surakin in https://github.com/element-hq/element-x-android/pull/3221 +* Rework FakeMatrixRoom so that it contains only lambdas. by @bmarty in https://github.com/element-hq/element-x-android/pull/3229 + Changes in Element X v0.4.16 (2024-07-05) ========================================= From 28ec0df5ea9018964bceea438f194f22693acb92 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 24 Jul 2024 19:05:45 +0000 Subject: [PATCH 012/186] Update activity to v1.9.1 --- 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 a1fede3e54..450b221d78 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ datastore = "1.0.0" constraintlayout = "2.1.4" constraintlayout_compose = "1.0.1" lifecycle = "2.7.0" -activity = "1.9.0" +activity = "1.9.1" media3 = "1.3.1" camera = "1.3.4" From 2254ed4322e1fe4b8438d3a6d18996ee26fcf51c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 00:17:54 +0000 Subject: [PATCH 013/186] Update dependency org.maplibre.gl:android-sdk to v11.1.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 a1fede3e54..04a5fc73bb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -177,7 +177,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:11.0.1" +maplibre = "org.maplibre.gl:android-sdk:11.1.0" maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.0" maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.0" opusencoder = "io.element.android:opusencoder:1.1.0" From 5fcb80970d4a3913f63e65f7aeb0c685cbe87121 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 25 Jul 2024 07:33:26 +0000 Subject: [PATCH 014/186] Update screenshots --- .../images/features.joinroom.impl_JoinRoomView_Day_1_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_1_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_1_en.png index 1392d3232b..0c9e5f8beb 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d124615503207b29dbd03c3e3831215f374f650cd45328b26c1313bddc48971 -size 107818 +oid sha256:b6319cbc723b9f3cf0b89c4ec5dc6098a7b6a2a2c053ee5bf5afc21830b8d3f6 +size 110855 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_1_en.png index 311a5b26cb..9c14a8b24a 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f57044edb93c4f599a02eee238d4cb5b070a4ca4dd34e66f2d4d55c71e0c044 -size 92785 +oid sha256:59666c1ca888ed089d7cf08fd75cc2f3e993b59c255317ad1af652aadfac8b4e +size 97026 From 524f20bb4079aa809af56bcc33843f94100b7714 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 24 Jul 2024 15:31:49 +0200 Subject: [PATCH 015/186] Timeline UI | MessageShield Support --- .../impl/timeline/TimelineStateProvider.kt | 5 +- .../components/MessageShieldPosition.kt | 25 ++++ .../timeline/components/MessageShieldView.kt | 120 ++++++++++++++++ .../components/TimelineItemEventRow.kt | 135 ++++++++++++++++-- .../event/TimelineItemEventFactory.kt | 1 + .../impl/timeline/model/TimelineItem.kt | 2 + .../event/TimelineItemEventContentProvider.kt | 12 ++ .../timeline/item/event/EventTimelineItem.kt | 1 + .../api/timeline/item/event/MessageShield.kt | 27 ++++ .../item/event/EventTimelineItemMapper.kt | 15 +- 10 files changed, 332 insertions(+), 11 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldPosition.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index f6b58e2799..e386efc781 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -35,6 +35,7 @@ import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails import io.element.android.libraries.matrix.ui.messages.reply.aProfileTimelineDetailsReady import kotlinx.collections.immutable.ImmutableList @@ -137,6 +138,7 @@ internal fun aTimelineItemEvent( debugInfo: TimelineItemDebugInfo = aTimelineItemDebugInfo(), timelineItemReactions: TimelineItemReactions = aTimelineItemReactions(), readReceiptState: TimelineItemReadReceipts = aTimelineItemReadReceipts(), + messageShield: MessageShield? = null, ): TimelineItem.Event { return TimelineItem.Event( id = UUID.randomUUID().toString(), @@ -159,7 +161,8 @@ internal fun aTimelineItemEvent( inReplyTo = inReplyTo, debugInfo = debugInfo, isThreaded = isThreaded, - origin = null + origin = null, + messageShield = messageShield, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldPosition.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldPosition.kt new file mode 100644 index 0000000000..41c424c56e --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldPosition.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.timeline.components + +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield + +sealed class MessageShieldPosition { + data class InBubble(val messageShield: MessageShield) : MessageShieldPosition() + data class OutOfBubble(val messageShield: MessageShield) : MessageShieldPosition() + object None : MessageShieldPosition() +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt new file mode 100644 index 0000000000..decb75fb2e --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.timeline.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.messageFromMeBackground +import io.element.android.libraries.designsystem.theme.messageFromOtherBackground +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield +import io.element.android.libraries.matrix.api.timeline.item.event.ShieldColor + +@Composable +internal fun MessageShieldView( + isMine: Boolean = false, + shield: MessageShield, + modifier: Modifier = Modifier +) { + val borderColor = if (shield.color == ShieldColor.RED) ElementTheme.colors.borderCriticalPrimary else ElementTheme.colors.bgSubtlePrimary + val iconColor = if (shield.color == ShieldColor.RED) ElementTheme.colors.iconCriticalPrimary else ElementTheme.colors.iconSecondary + + val backgroundBubbleColor = when { + isMine -> ElementTheme.colors.messageFromMeBackground + else -> ElementTheme.colors.messageFromOtherBackground + } + Row( + verticalAlignment = Alignment.Top, + modifier = modifier + .background(backgroundBubbleColor, RoundedCornerShape(8.dp)) + .border(1.dp, borderColor, RoundedCornerShape(8.dp)) + .padding(8.dp) + ) { + Icon( + imageVector = shield.toIcon(), + contentDescription = null, + modifier = Modifier.size(15.dp), + tint = iconColor, + ) + Spacer(modifier = Modifier.size(4.dp)) + val textColor = if (shield.color == ShieldColor.RED) ElementTheme.colors.textCriticalPrimary else ElementTheme.colors.textSecondary + Text( + text = shield.message, + style = ElementTheme.typography.fontBodyXsRegular, + color = textColor + ) + } +} + +@Composable +private fun MessageShield.toIcon(): ImageVector { + return when (this.color) { + ShieldColor.RED -> CompoundIcons.Error() + ShieldColor.GREY -> CompoundIcons.InfoSolid() + } +} + +@PreviewsDayNight +@Composable +internal fun MessageShieldViewPreviews() { + ElementPreview { + Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { + MessageShieldView( + shield = MessageShield( + message = "The authenticity of this encrypted message can't be guaranteed on this device.", + color = ShieldColor.GREY + ) + ) + MessageShieldView( + isMine = true, + shield = MessageShield( + message = "The authenticity of this encrypted message can't be guaranteed on this device.", + color = ShieldColor.GREY + ) + ) + MessageShieldView( + shield = MessageShield( + message = "Encrypted by a device not verified by its owner.", + color = ShieldColor.RED + ) + ) + MessageShieldView( + shield = MessageShield( + message = "Encrypted by an unknown or deleted device.", + color = ShieldColor.RED + ) + ) + } + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index a2ac0ac7b1..bc567c1250 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -17,6 +17,7 @@ package io.element.android.features.messages.impl.timeline.components import android.annotation.SuppressLint +import android.content.res.Configuration import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.Orientation @@ -50,6 +51,7 @@ import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.invisibleToUser import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTag +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp @@ -75,6 +77,8 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent +import io.element.android.features.messages.impl.timeline.model.event.aGreyShield +import io.element.android.features.messages.impl.timeline.model.event.aRedShield import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.features.messages.impl.timeline.model.event.canBeRepliedTo @@ -277,6 +281,7 @@ private fun TimelineItemEventRowContent( val ( sender, message, + shield, reactions, ) = createRefs() @@ -328,6 +333,29 @@ private fun TimelineItemEventRowContent( ) } + val shieldPosition = event.shieldPosition() + if (shieldPosition is MessageShieldPosition.OutOfBubble) { + MessageShieldView( + isMine = event.isMine, + shield = shieldPosition.messageShield, + modifier = Modifier + .constrainAs(shield) { + top.linkTo(message.bottom, margin = (-4).dp) + linkStartOrEnd(event) + } + .padding( + // Note: due to the applied constraints, start is left for other's message and right for mine + // In design we want a offset of 6.dp compare to the bubble, so start is 22.dp (16 + 6) + start = when { + event.isMine -> 22.dp + timelineRoomInfo.isDm -> 22.dp + else -> 22.dp + BUBBLE_INCOMING_OFFSET + }, + end = 16.dp + ), + ) + } + // Reactions if (event.reactionsState.reactions.isNotEmpty()) { TimelineItemReactionsView( @@ -339,7 +367,11 @@ private fun TimelineItemEventRowContent( onMoreReactionsClick = { onMoreReactionsClick(event) }, modifier = Modifier .constrainAs(reactions) { - top.linkTo(message.bottom, margin = (-4).dp) + if (shieldPosition is MessageShieldPosition.OutOfBubble) { + top.linkTo(shield.bottom, margin = (-4).dp) + } else { + top.linkTo(message.bottom, margin = (-4).dp) + } linkStartOrEnd(event) } .zIndex(1f) @@ -472,6 +504,7 @@ private fun MessageEventBubbleContent( @Composable fun CommonLayout( timestampPosition: TimestampPosition, + messageShieldPosition: MessageShieldPosition, showThreadDecoration: Boolean, inReplyToDetails: InReplyToDetails?, modifier: Modifier = Modifier, @@ -510,13 +543,30 @@ private fun MessageEventBubbleContent( canShrinkContent = canShrinkContent, modifier = timestampLayoutModifier, ) { onContentLayoutChange -> - TimelineItemEventContentView( - content = event.content, - onLinkClick = onLinkClick, - eventSink = eventSink, - onContentLayoutChange = onContentLayoutChange, - modifier = contentModifier - ) + + if (messageShieldPosition is MessageShieldPosition.InBubble) { + Column { + TimelineItemEventContentView( + content = event.content, + onLinkClick = onLinkClick, + eventSink = eventSink, + onContentLayoutChange = onContentLayoutChange, + modifier = contentModifier + ) + MessageShieldView( + modifier = Modifier.padding(start = 8.dp, end = 8.dp), + shield = messageShieldPosition.messageShield, + ) + } + } else { + TimelineItemEventContentView( + content = event.content, + onLinkClick = onLinkClick, + eventSink = eventSink, + onContentLayoutChange = onContentLayoutChange, + modifier = contentModifier + ) + } } } val inReplyTo = @Composable { inReplyTo: InReplyToDetails -> @@ -551,9 +601,11 @@ private fun MessageEventBubbleContent( is TimelineItemPollContent -> TimestampPosition.Below else -> TimestampPosition.Default } + val messageShieldPosition = event.shieldPosition() CommonLayout( showThreadDecoration = event.isThreaded, - timestampPosition = timestampPosition, + messageShieldPosition = messageShieldPosition, + timestampPosition = if (messageShieldPosition is MessageShieldPosition.InBubble) TimestampPosition.Below else timestampPosition, inReplyToDetails = event.inReplyTo, canShrinkContent = event.content is TimelineItemVoiceContent, modifier = bubbleModifier.semantics(mergeDescendants = true) { @@ -590,3 +642,68 @@ internal fun TimelineItemEventRowPreview() = ElementPreview { } } } + +@Preview( + name = "Encryption Shields" +) +@Preview( + name = "Encryption Shields - Night", + uiMode = Configuration.UI_MODE_NIGHT_YES +) +@Composable +internal fun TimelineItemEventRowShieldsPreview() = ElementPreview { + Column { + ATimelineItemEventRow( + event = aTimelineItemEvent( + senderDisplayName = "Sender with a super long name that should ellipsize", + isMine = true, + content = aTimelineItemTextContent( + body = "Message sent from unsigned device" + ), + groupPosition = TimelineItemGroupPosition.First, + messageShield = aRedShield() + ), + ) + ATimelineItemEventRow( + event = aTimelineItemEvent( + senderDisplayName = "Sender with a super long name that should ellipsize", + content = aTimelineItemTextContent( + body = "Short Message with authenticity warning" + ), + groupPosition = TimelineItemGroupPosition.Middle, + messageShield = aGreyShield() + ), + ) + ATimelineItemEventRow( + event = aTimelineItemEvent( + isMine = true, + content = aTimelineItemImageContent().copy( + aspectRatio = 2.5f + ), + groupPosition = TimelineItemGroupPosition.Last, + messageShield = aRedShield() + ), + ) + ATimelineItemEventRow( + event = aTimelineItemEvent( + content = aTimelineItemImageContent().copy( + aspectRatio = 2.5f + ), + groupPosition = TimelineItemGroupPosition.Last, + messageShield = aGreyShield() + ), + ) + } +} + +private fun TimelineItem.Event.shieldPosition(): MessageShieldPosition { + if (this.messageShield == null) return MessageShieldPosition.None + return when (this.content) { + is TimelineItemImageContent, + is TimelineItemVideoContent, + is TimelineItemStickerContent, + is TimelineItemLocationContent, + is TimelineItemPollContent -> MessageShieldPosition.OutOfBubble(this.messageShield) + else -> MessageShieldPosition.InBubble(this.messageShield) + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt index c5d303b3f1..ae2dd3e39c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt @@ -85,6 +85,7 @@ class TimelineItemEventFactory @Inject constructor( isThreaded = currentTimelineItem.event.isThreaded(), debugInfo = currentTimelineItem.event.debugInfo, origin = currentTimelineItem.event.origin, + messageShield = currentTimelineItem.event.messageShield, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt index f77db70506..73bfac5a9d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName @@ -82,6 +83,7 @@ sealed interface TimelineItem { val isThreaded: Boolean, val debugInfo: TimelineItemDebugInfo, val origin: TimelineItemEventOrigin?, + val messageShield: MessageShield?, ) : TimelineItem { val showSenderInformation = groupPosition.isNew() && !isMine diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt index 29fa048e1f..e103c44d1c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt @@ -21,6 +21,8 @@ import android.text.style.StyleSpan import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.core.text.buildSpannedString import androidx.core.text.inSpans +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield +import io.element.android.libraries.matrix.api.timeline.item.event.ShieldColor import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent class TimelineItemEventContentProvider : PreviewParameterProvider { @@ -102,3 +104,13 @@ fun aTimelineItemStateEventContent( ) = TimelineItemStateEventContent( body = body, ) + +fun aGreyShield() = MessageShield( + message = "The authenticity of this encrypted message can't be guaranteed on this device.", + color = ShieldColor.GREY +) + +fun aRedShield() = MessageShield( + message = "Encrypted by a device not verified by its owner.", + color = ShieldColor.RED +) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt index fa15f8f096..170fedfa28 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt @@ -38,6 +38,7 @@ data class EventTimelineItem( val content: EventContent, val debugInfo: TimelineItemDebugInfo, val origin: TimelineItemEventOrigin?, + val messageShield: MessageShield?, ) { fun inReplyTo(): InReplyTo? { return (content as? MessageContent)?.inReplyTo diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt new file mode 100644 index 0000000000..58fc96d8b1 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.timeline.item.event + +data class MessageShield( + val message: String, + val color: ShieldColor, +) + +enum class ShieldColor { + RED, + GREY +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt index dd0bdabd7f..f80b877baa 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt @@ -23,14 +23,17 @@ import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugIn import io.element.android.libraries.matrix.api.timeline.item.event.EventReaction import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails import io.element.android.libraries.matrix.api.timeline.item.event.ReactionSender import io.element.android.libraries.matrix.api.timeline.item.event.Receipt +import io.element.android.libraries.matrix.api.timeline.item.event.ShieldColor import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import org.matrix.rustcomponents.sdk.Reaction +import org.matrix.rustcomponents.sdk.ShieldState import org.matrix.rustcomponents.sdk.EventSendState as RustEventSendState import org.matrix.rustcomponents.sdk.EventTimelineItem as RustEventTimelineItem import org.matrix.rustcomponents.sdk.EventTimelineItemDebugInfo as RustEventTimelineItemDebugInfo @@ -55,7 +58,8 @@ class EventTimelineItemMapper(private val contentMapper: TimelineEventContentMap timestamp = it.timestamp().toLong(), content = contentMapper.map(it.content()), debugInfo = it.debugInfo().map(), - origin = it.origin()?.map() + origin = it.origin()?.map(), + messageShield = it.getShield(false)?.map(), ) } } @@ -128,3 +132,12 @@ private fun RustEventItemOrigin.map(): TimelineItemEventOrigin { RustEventItemOrigin.PAGINATION -> TimelineItemEventOrigin.PAGINATION } } + +private fun ShieldState?.map(): MessageShield? { + return when (this) { + is ShieldState.Grey -> MessageShield(message = this.message, color = ShieldColor.GREY) + is ShieldState.Red -> MessageShield(message = this.message, color = ShieldColor.RED) + ShieldState.None, + null -> null + } +} From 0748bc8c470d544ef504035f6a0a1a54033efa0e Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 25 Jul 2024 09:48:58 +0200 Subject: [PATCH 016/186] Message Shields - i18n --- .../components/TimelineItemEventRow.kt | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index bc567c1250..486732d7c7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -37,6 +37,7 @@ import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment @@ -696,14 +697,29 @@ internal fun TimelineItemEventRowShieldsPreview() = ElementPreview { } } +@Composable +@ReadOnlyComposable private fun TimelineItem.Event.shieldPosition(): MessageShieldPosition { - if (this.messageShield == null) return MessageShieldPosition.None + val shield = this.messageShield ?: return MessageShieldPosition.None + + // sdk returns raw human readable strings, add i18n support + val localizedMessage = when (shield.message) { + "The authenticity of this encrypted message can't be guaranteed on this device." -> stringResource( + CommonStrings.event_shield_reason_authenticity_not_guaranteed + ) + "Encrypted by a device not verified by its owner." -> stringResource(CommonStrings.event_shield_reason_unsigned_device) + "Encrypted by an unknown or deleted device." -> stringResource(CommonStrings.event_shield_reason_unknown_device) + "Encrypted by an unverified user." -> stringResource(CommonStrings.event_shield_reason_unverified_identity) + else -> shield.message + } + val localShield = shield.copy(message = localizedMessage) + return when (this.content) { is TimelineItemImageContent, is TimelineItemVideoContent, is TimelineItemStickerContent, is TimelineItemLocationContent, - is TimelineItemPollContent -> MessageShieldPosition.OutOfBubble(this.messageShield) - else -> MessageShieldPosition.InBubble(this.messageShield) + is TimelineItemPollContent -> MessageShieldPosition.OutOfBubble(localShield) + else -> MessageShieldPosition.InBubble(localShield) } } From b3b90a3b178c223a720d2aee287f16e306bf0f64 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 25 Jul 2024 10:00:36 +0200 Subject: [PATCH 017/186] MessageShields | Fix test compilation --- .../android/libraries/matrix/test/timeline/TimelineFixture.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt index d53bc7b18f..8be4da3876 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt @@ -28,6 +28,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventTimeline import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.MessageType import io.element.android.libraries.matrix.api.timeline.item.event.PollContent import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent @@ -57,6 +58,7 @@ fun anEventTimelineItem( timestamp: Long = 0L, content: EventContent = aProfileChangeMessageContent(), debugInfo: TimelineItemDebugInfo = aTimelineItemDebugInfo(), + messageShield: MessageShield? = null, ) = EventTimelineItem( eventId = eventId, transactionId = transactionId, @@ -73,6 +75,7 @@ fun anEventTimelineItem( content = content, debugInfo = debugInfo, origin = null, + messageShield = messageShield, ) fun aProfileTimelineDetails( From eec0e371f60ea012b062f1885cde4b0a0dbaf5dc Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 24 Jul 2024 18:32:26 +0200 Subject: [PATCH 018/186] SSS : enhance getBaseClientBuilder to avoid mistakes. --- .../matrix/impl/RustMatrixClientFactory.kt | 27 ++++++++++++++++--- .../auth/RustMatrixAuthenticationService.kt | 4 ++- 2 files changed, 27 insertions(+), 4 deletions(-) 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 96d8e4939d..51e71f3855 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 @@ -54,7 +54,11 @@ class RustMatrixClientFactory @Inject constructor( val client = getBaseClientBuilder( sessionPath = sessionData.sessionPath, passphrase = sessionData.passphrase, - useSimplifiedSlidingSync = appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first(), + slidingSync = if (appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first()) { + ClientBuilderSlidingSync.Simplified + } else { + ClientBuilderSlidingSync.Restored + }, ) .homeserverUrl(sessionData.homeserverUrl) .username(sessionData.userId) @@ -86,7 +90,7 @@ class RustMatrixClientFactory @Inject constructor( sessionPath: String, passphrase: String?, slidingSyncProxy: String? = null, - useSimplifiedSlidingSync: Boolean = false, + slidingSync: ClientBuilderSlidingSync, ): ClientBuilder { return ClientBuilder() .sessionPath(sessionPath) @@ -96,7 +100,13 @@ class RustMatrixClientFactory @Inject constructor( .addRootCertificates(userCertificatesProvider.provides()) .autoEnableBackups(true) .autoEnableCrossSigning(true) - .simplifiedSlidingSync(useSimplifiedSlidingSync) + .run { + when (slidingSync) { + ClientBuilderSlidingSync.Restored -> this + ClientBuilderSlidingSync.Discovered -> requiresSlidingSync() + ClientBuilderSlidingSync.Simplified -> simplifiedSlidingSync(true) + } + } .run { // Workaround for non-nullable proxy parameter in the SDK, since each call to the ClientBuilder returns a new reference we need to keep proxyProvider.provides()?.let { proxy(it) } ?: this @@ -104,6 +114,17 @@ class RustMatrixClientFactory @Inject constructor( } } +enum class ClientBuilderSlidingSync { + // The proxy will be supplied when restoring the Session. + Restored, + + // A proxy must be discovered whilst building the session. + Discovered, + + // Use Simplified Sliding Sync (discovery isn't a thing yet). + Simplified, +} + private fun SessionData.toSession() = Session( accessToken = accessToken, refreshToken = refreshToken, 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 8c0546fa8b..e1ff0811e1 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 @@ -29,6 +29,7 @@ import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.impl.ClientBuilderSlidingSync import io.element.android.libraries.matrix.impl.RustMatrixClientFactory import io.element.android.libraries.matrix.impl.auth.qrlogin.QrErrorMapper import io.element.android.libraries.matrix.impl.auth.qrlogin.SdkQrCodeLoginData @@ -210,6 +211,7 @@ class RustMatrixAuthenticationService @Inject constructor( sessionPath = sessionPath, passphrase = pendingPassphrase, slidingSyncProxy = AuthenticationConfig.SLIDING_SYNC_PROXY_URL, + slidingSync = ClientBuilderSlidingSync.Discovered, ) .buildWithQrCode( qrCodeData = (qrCodeData as SdkQrCodeLoginData).rustQrCodeData, @@ -251,8 +253,8 @@ class RustMatrixAuthenticationService @Inject constructor( sessionPath = sessionPath, passphrase = pendingPassphrase, slidingSyncProxy = AuthenticationConfig.SLIDING_SYNC_PROXY_URL, + slidingSync = ClientBuilderSlidingSync.Discovered, ) - .requiresSlidingSync() private fun clear() { currentClient?.close() From 44728cb6e1f5d996ab29bcf94a5563fca772138c Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 25 Jul 2024 10:22:15 +0200 Subject: [PATCH 019/186] review: Konsist fix --- .../messages/impl/timeline/components/MessageShieldView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt index decb75fb2e..2efa888bb7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt @@ -87,7 +87,7 @@ private fun MessageShield.toIcon(): ImageVector { @PreviewsDayNight @Composable -internal fun MessageShieldViewPreviews() { +internal fun MessageShieldViewPreview() { ElementPreview { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { MessageShieldView( From bb76ad928417332775d2abd2491bb28db1e2c480 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 14:24:58 +0000 Subject: [PATCH 020/186] Update dependency io.sentry:sentry-android to v7.12.1 --- 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 0609a17dc2..edce201825 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -187,7 +187,7 @@ play_services_oss_licenses = "com.google.android.gms:play-services-oss-licenses: # Analytics posthog = "com.posthog:posthog-android:3.4.2" -sentry = "io.sentry:sentry-android:7.12.0" +sentry = "io.sentry:sentry-android:7.12.1" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.23.1" From 03a0e4fa0859478935f7701b3e6ca36205ce863d Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 25 Jul 2024 18:37:46 +0200 Subject: [PATCH 021/186] Pinned event : hide/show banner on timeline scroll --- .../features/messages/impl/MessagesView.kt | 17 ++++++- .../pinned/banner/PinnedMessagesBannerView.kt | 7 +-- .../messages/impl/timeline/TimelineView.kt | 2 +- .../designsystem/utils/LazyListState.kt | 46 +++++++++++++++++++ 4 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/LazyListState.kt 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 427ab8d10a..b845953ec8 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 @@ -16,6 +16,9 @@ package io.element.android.features.messages.impl +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -33,6 +36,7 @@ import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme @@ -101,6 +105,7 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.utils.KeepScreenOn import io.element.android.libraries.designsystem.utils.OnLifecycleEvent +import io.element.android.libraries.designsystem.utils.isScrollingUp import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.matrix.api.core.UserId @@ -375,6 +380,7 @@ private fun MessagesViewContent( }, content = { paddingValues -> Box(modifier = Modifier.padding(paddingValues)) { + val timelineLazyListState = rememberLazyListState() TimelineView( state = state.timelineState, typingNotificationState = state.typingNotificationState, @@ -389,8 +395,17 @@ private fun MessagesViewContent( onReadReceiptClick = onReadReceiptClick, forceJumpToBottomVisibility = forceJumpToBottomVisibility, onJoinCallClick = onJoinCallClick, + lazyListState = timelineLazyListState, ) - PinnedMessagesBannerView(state = state.pinnedMessagesBannerState) + AnimatedVisibility( + visible = state.pinnedMessagesBannerState.displayBanner && timelineLazyListState.isScrollingUp(), + enter = expandVertically(), + exit = shrinkVertically(), + ) { + PinnedMessagesBannerView( + state = state.pinnedMessagesBannerState, + ) + } } }, sheetContent = { subcomposing: Boolean -> diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index 38e3562c5f..dbae6a6133 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -32,12 +32,15 @@ import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawBehind @@ -63,8 +66,6 @@ fun PinnedMessagesBannerView( state: PinnedMessagesBannerState, modifier: Modifier = Modifier, ) { - if (!state.displayBanner) return - val borderColor = ElementTheme.colors.pinnedMessageBannerBorder Row( modifier = modifier @@ -199,6 +200,6 @@ private fun PinnedMessageItem( @Composable fun PinnedMessagesBannerViewPreview(@PreviewParameter(PinnedMessagesBannerStateProvider::class) state: PinnedMessagesBannerState) = ElementPreview { PinnedMessagesBannerView( - state = state + state = state, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index eff2019a11..b640d9d450 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -90,6 +90,7 @@ fun TimelineView( onReadReceiptClick: (TimelineItem.Event) -> Unit, onJoinCallClick: () -> Unit, modifier: Modifier = Modifier, + lazyListState: LazyListState = rememberLazyListState(), forceJumpToBottomVisibility: Boolean = false ) { fun clearFocusRequestState() { @@ -109,7 +110,6 @@ fun TimelineView( } val context = LocalContext.current - val lazyListState = rememberLazyListState() // Disable reverse layout when TalkBack is enabled to avoid incorrect ordering issues seen in the current Compose UI version val useReverseLayout = remember { val accessibilityManager = context.getSystemService(AccessibilityManager::class.java) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/LazyListState.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/LazyListState.kt new file mode 100644 index 0000000000..7e1eb53461 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/LazyListState.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.utils + +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue + +/** + * Returns whether the lazy list is currently scrolling up. + */ +@Composable +fun LazyListState.isScrollingUp(): Boolean { + var previousIndex by remember(this) { mutableIntStateOf(firstVisibleItemIndex) } + var previousScrollOffset by remember(this) { mutableIntStateOf(firstVisibleItemScrollOffset) } + return remember(this) { + derivedStateOf { + if (previousIndex != firstVisibleItemIndex) { + previousIndex > firstVisibleItemIndex + } else { + previousScrollOffset >= firstVisibleItemScrollOffset + }.also { + previousIndex = firstVisibleItemIndex + previousScrollOffset = firstVisibleItemScrollOffset + } + } + }.value +} From 183e392fe9a9744afc99b949eedead04ac325158 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 25 Jul 2024 21:04:35 +0200 Subject: [PATCH 022/186] Pinned event : create the feature flag --- .../android/libraries/featureflag/api/FeatureFlags.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 616a549e63..9fda418606 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -120,4 +120,11 @@ enum class FeatureFlags( defaultValue = { it.buildType != BuildType.RELEASE }, isFinished = false, ), + PinnedEvents( + key = "feature.pinnedEvents", + title = "Pinned Events", + description = "Allow user to pin events in a room", + defaultValue = { false }, + isFinished = false, + ) } From 0149007dd407f88f03572bd4d64830139ee4966b Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 26 Jul 2024 18:20:03 +0200 Subject: [PATCH 023/186] Timeline Action : refactor how it's computed and align with iOS --- .../messages/impl/MessagesPresenter.kt | 31 ++- .../features/messages/impl/MessagesState.kt | 5 +- .../messages/impl/MessagesStateProvider.kt | 24 +- .../features/messages/impl/MessagesView.kt | 7 +- .../messages/impl/UserEventPermissions.kt | 28 +++ .../impl/actionlist/ActionListEvents.kt | 6 +- .../impl/actionlist/ActionListPresenter.kt | 201 ++++++---------- .../impl/timeline/TimelineStateProvider.kt | 2 + .../components/TimelineItemEventRow.kt | 3 +- .../event/TimelineItemEventFactory.kt | 1 + .../impl/timeline/model/TimelineItem.kt | 3 + .../model/event/TimelineItemEventContent.kt | 30 +-- .../messages/impl/MessagesPresenterTest.kt | 23 +- .../messages/impl/MessagesViewTest.kt | 29 +-- .../actionlist/ActionListPresenterTest.kt | 218 ++++++++++-------- .../impl/fixtures/MessageEventFixtures.kt | 2 + .../groups/TimelineItemGrouperTest.kt | 1 + .../RedactedVoiceMessageManagerTest.kt | 1 + .../timeline/item/event/EventTimelineItem.kt | 1 + .../item/event/EventTimelineItemMapper.kt | 1 + .../matrix/test/timeline/TimelineFixture.kt | 2 + 21 files changed, 323 insertions(+), 296 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/UserEventPermissions.kt 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 b13a95d4f2..2a1ea9dd51 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 @@ -20,6 +20,7 @@ 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 @@ -131,10 +132,9 @@ class MessagesPresenter @AssistedInject constructor( val readReceiptBottomSheetState = readReceiptBottomSheetPresenter.present() val syncUpdateFlow = room.syncUpdateFlow.collectAsState() - val userHasPermissionToSendMessage by room.canSendMessageAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = syncUpdateFlow.value) - val userHasPermissionToRedactOwn by room.canRedactOwnAsState(updateKey = syncUpdateFlow.value) - val userHasPermissionToRedactOther by room.canRedactOtherAsState(updateKey = syncUpdateFlow.value) - val userHasPermissionToSendReaction by room.canSendMessageAsState(type = MessageEventType.REACTION, updateKey = syncUpdateFlow.value) + + val userEventPermissions by userEventPermissions(syncUpdateFlow.value) + val roomName: AsyncData by remember { derivedStateOf { roomInfo?.name?.let { AsyncData.Success(it) } ?: AsyncData.Uninitialized } } @@ -211,11 +211,8 @@ class MessagesPresenter @AssistedInject constructor( roomName = roomName, roomAvatar = roomAvatar, heroes = heroes, - userHasPermissionToSendMessage = userHasPermissionToSendMessage, - userHasPermissionToRedactOwn = userHasPermissionToRedactOwn, - userHasPermissionToRedactOther = userHasPermissionToRedactOther, - userHasPermissionToSendReaction = userHasPermissionToSendReaction, composerState = composerState, + userEventPermissions = userEventPermissions, voiceMessageComposerState = voiceMessageComposerState, timelineState = timelineState, typingNotificationState = typingNotificationState, @@ -235,6 +232,24 @@ class MessagesPresenter @AssistedInject constructor( ) } + @Composable + private fun userEventPermissions(updateKey: Long): State { + val userHasPermissionToSendMessage by room.canSendMessageAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = updateKey) + val userHasPermissionToRedactOwn by room.canRedactOwnAsState(updateKey = updateKey) + val userHasPermissionToRedactOther by room.canRedactOtherAsState(updateKey = updateKey) + val userHasPermissionToSendReaction by room.canSendMessageAsState(type = MessageEventType.REACTION, updateKey = updateKey) + return remember { + derivedStateOf { + UserEventPermissions( + canSendMessage = userHasPermissionToSendMessage, + canRedactOwn = userHasPermissionToRedactOwn, + canRedactOther = userHasPermissionToRedactOther, + canSendReaction = userHasPermissionToSendReaction, + ) + } + } + } + private fun MatrixRoomInfo.avatarData(): AvatarData { return AvatarData( id = id.value, 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 e8657d70bd..99e5b50de8 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 @@ -37,10 +37,7 @@ data class MessagesState( val roomName: AsyncData, val roomAvatar: AsyncData, val heroes: ImmutableList, - val userHasPermissionToSendMessage: Boolean, - val userHasPermissionToRedactOwn: Boolean, - val userHasPermissionToRedactOther: Boolean, - val userHasPermissionToSendReaction: Boolean, + val userEventPermissions: UserEventPermissions, val composerState: MessageComposerState, val voiceMessageComposerState: VoiceMessageComposerState, val timelineState: TimelineState, 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 1396d3e17c..082edb1ca3 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 @@ -53,7 +53,7 @@ open class MessagesStateProvider : PreviewParameterProvider { aMessagesState(), aMessagesState(hasNetworkConnection = false), aMessagesState(composerState = aMessageComposerState(showAttachmentSourcePicker = true)), - aMessagesState(userHasPermissionToSendMessage = false), + aMessagesState(userEventPermissions = aUserEventPermissions(canSendMessage = false)), aMessagesState(showReinvitePrompt = true), aMessagesState( roomName = AsyncData.Uninitialized, @@ -93,10 +93,7 @@ open class MessagesStateProvider : PreviewParameterProvider { fun aMessagesState( roomName: AsyncData = AsyncData.Success("Room name"), roomAvatar: AsyncData = AsyncData.Success(AvatarData("!id:domain", "Room name", size = AvatarSize.TimelineRoom)), - userHasPermissionToSendMessage: Boolean = true, - userHasPermissionToRedactOwn: Boolean = false, - userHasPermissionToRedactOther: Boolean = false, - userHasPermissionToSendReaction: Boolean = true, + userEventPermissions: UserEventPermissions = aUserEventPermissions(), composerState: MessageComposerState = aMessageComposerState( textEditorState = TextEditorState.Rich(aRichTextEditorState(initialText = "Hello", initialFocus = true)), isFullScreen = false, @@ -122,10 +119,7 @@ fun aMessagesState( roomName = roomName, roomAvatar = roomAvatar, heroes = persistentListOf(), - userHasPermissionToSendMessage = userHasPermissionToSendMessage, - userHasPermissionToRedactOwn = userHasPermissionToRedactOwn, - userHasPermissionToRedactOther = userHasPermissionToRedactOther, - userHasPermissionToSendReaction = userHasPermissionToSendReaction, + userEventPermissions = userEventPermissions, composerState = composerState, voiceMessageComposerState = voiceMessageComposerState, typingNotificationState = aTypingNotificationState(), @@ -145,6 +139,18 @@ fun aMessagesState( eventSink = eventSink, ) +fun aUserEventPermissions( + canRedactOwn: Boolean = false, + canRedactOther: Boolean = false, + canSendMessage: Boolean = true, + canSendReaction: Boolean = true, +) = UserEventPermissions( + canRedactOwn = canRedactOwn, + canRedactOther = canRedactOther, + canSendMessage = canSendMessage, + canSendReaction = canSendReaction, +) + fun aReactionSummaryState( target: ReactionSummaryState.Summary? = null, eventSink: (ReactionSummaryEvents) -> Unit = {} 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 24439c0c75..0a868fac12 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 @@ -154,10 +154,7 @@ fun MessagesView( state.actionListState.eventSink( ActionListEvents.ComputeForMessage( event = event, - canRedactOwn = state.userHasPermissionToRedactOwn, - canRedactOther = state.userHasPermissionToRedactOther, - canSendMessage = state.userHasPermissionToSendMessage, - canSendReaction = state.userHasPermissionToSendReaction, + userEventPermissions = state.userEventPermissions, ) ) } @@ -408,7 +405,7 @@ private fun MessagesViewComposerBottomSheetContents( subcomposing: Boolean, state: MessagesState, ) { - if (state.userHasPermissionToSendMessage) { + if (state.userEventPermissions.canSendMessage) { Column(modifier = Modifier.fillMaxWidth()) { MentionSuggestionsPickerView( modifier = Modifier 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 new file mode 100644 index 0000000000..84b60ae228 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/UserEventPermissions.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl + +/** + * Represents the permissions a user has in a room. + * It's dependent of the user's power level in the room. + */ +data class UserEventPermissions( + val canRedactOwn: Boolean, + val canRedactOther: Boolean, + val canSendMessage: Boolean, + val canSendReaction: Boolean, +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt index e486c1ae2b..407d18afb7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt @@ -16,15 +16,13 @@ package io.element.android.features.messages.impl.actionlist +import io.element.android.features.messages.impl.UserEventPermissions import io.element.android.features.messages.impl.timeline.model.TimelineItem sealed interface ActionListEvents { data object Clear : ActionListEvents data class ComputeForMessage( val event: TimelineItem.Event, - val canRedactOwn: Boolean, - val canRedactOther: Boolean, - val canSendMessage: Boolean, - val canSendReaction: Boolean, + val userEventPermissions: UserEventPermissions, ) : ActionListEvents } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index d1a19b600d..0f4379cffb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -23,15 +23,17 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import io.element.android.features.messages.impl.UserEventPermissions import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent import io.element.android.features.messages.impl.timeline.model.event.canBeCopied +import io.element.android.features.messages.impl.timeline.model.event.canBeForwarded import io.element.android.features.messages.impl.timeline.model.event.canReact import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.preferences.api.store.AppPreferencesStore @@ -58,10 +60,7 @@ class ActionListPresenter @Inject constructor( ActionListEvents.Clear -> target.value = ActionListState.Target.None is ActionListEvents.ComputeForMessage -> localCoroutineScope.computeForMessage( timelineItem = event.event, - userCanRedactOwn = event.canRedactOwn, - userCanRedactOther = event.canRedactOther, - userCanSendMessage = event.canSendMessage, - userCanSendReaction = event.canSendReaction, + usersEventPermissions = event.userEventPermissions, isDeveloperModeEnabled = isDeveloperModeEnabled, target = target, ) @@ -76,136 +75,18 @@ class ActionListPresenter @Inject constructor( private fun CoroutineScope.computeForMessage( timelineItem: TimelineItem.Event, - userCanRedactOwn: Boolean, - userCanRedactOther: Boolean, - userCanSendMessage: Boolean, - userCanSendReaction: Boolean, + usersEventPermissions: UserEventPermissions, isDeveloperModeEnabled: Boolean, target: MutableState ) = launch { target.value = ActionListState.Target.Loading(timelineItem) - val canRedact = timelineItem.isMine && userCanRedactOwn || !timelineItem.isMine && userCanRedactOther - val actions = - when (timelineItem.content) { - is TimelineItemCallNotifyContent -> { - if (isDeveloperModeEnabled) { - listOf(TimelineItemAction.ViewSource) - } else { - emptyList() - } - } - is TimelineItemRedactedContent -> { - if (isDeveloperModeEnabled) { - listOf(TimelineItemAction.ViewSource) - } else { - emptyList() - } - } - is TimelineItemStateContent -> { - buildList { - add(TimelineItemAction.Copy) - if (timelineItem.isRemote) { - add(TimelineItemAction.CopyLink) - } - if (isDeveloperModeEnabled) { - add(TimelineItemAction.ViewSource) - } - } - } - is TimelineItemPollContent -> { - val canEndPoll = timelineItem.isRemote && - !timelineItem.content.isEnded && - (timelineItem.isMine || canRedact) - buildList { - if (timelineItem.isRemote) { - // Can only reply or forward messages already uploaded to the server - add(TimelineItemAction.Reply) - } - if (timelineItem.isRemote && timelineItem.isEditable) { - add(TimelineItemAction.Edit) - } - if (canEndPoll) { - add(TimelineItemAction.EndPoll) - } - if (timelineItem.content.canBeCopied()) { - add(TimelineItemAction.Copy) - } - if (timelineItem.isRemote) { - add(TimelineItemAction.CopyLink) - } - if (isDeveloperModeEnabled) { - add(TimelineItemAction.ViewSource) - } - if (!timelineItem.isMine) { - add(TimelineItemAction.ReportContent) - } - if (canRedact) { - add(TimelineItemAction.Redact) - } - } - } - is TimelineItemVoiceContent -> { - buildList { - if (timelineItem.isRemote) { - add(TimelineItemAction.Reply) - add(TimelineItemAction.Forward) - add(TimelineItemAction.CopyLink) - } - if (isDeveloperModeEnabled) { - add(TimelineItemAction.ViewSource) - } - if (!timelineItem.isMine) { - add(TimelineItemAction.ReportContent) - } - if (canRedact) { - add(TimelineItemAction.Redact) - } - } - } - is TimelineItemLegacyCallInviteContent -> { - buildList { - if (isDeveloperModeEnabled) { - add(TimelineItemAction.ViewSource) - } - } - } - else -> buildList { - if (timelineItem.isRemote) { - // Can only reply or forward messages already uploaded to the server - if (userCanSendMessage) { - if (timelineItem.isThreaded) { - add(TimelineItemAction.ReplyInThread) - } else { - add(TimelineItemAction.Reply) - } - } - // Stickers can't be forwarded (yet) so we don't show the option - // See https://github.com/element-hq/element-x-android/issues/2161 - if (!timelineItem.isSticker) { - add(TimelineItemAction.Forward) - } - } - if (timelineItem.isEditable) { - add(TimelineItemAction.Edit) - } - if (timelineItem.content.canBeCopied()) { - add(TimelineItemAction.Copy) - } - if (timelineItem.isRemote) { - add(TimelineItemAction.CopyLink) - } - if (isDeveloperModeEnabled) { - add(TimelineItemAction.ViewSource) - } - if (!timelineItem.isMine) { - add(TimelineItemAction.ReportContent) - } - if (canRedact) { - add(TimelineItemAction.Redact) - } - } - } - val displayEmojiReactions = userCanSendReaction && + + val actions = buildActions( + timelineItem = timelineItem, + usersEventPermissions = usersEventPermissions, + isDeveloperModeEnabled = isDeveloperModeEnabled, + ) + val displayEmojiReactions = usersEventPermissions.canSendReaction && timelineItem.isRemote && timelineItem.content.canReact() if (actions.isNotEmpty() || displayEmojiReactions) { @@ -219,3 +100,61 @@ class ActionListPresenter @Inject constructor( } } } + +private fun buildActions( + timelineItem: TimelineItem.Event, + usersEventPermissions: UserEventPermissions, + isDeveloperModeEnabled: Boolean, +): List { + val canRedact = timelineItem.isMine && usersEventPermissions.canRedactOwn || !timelineItem.isMine && usersEventPermissions.canRedactOther + return buildList { + if (timelineItem.canBeRepliedTo && usersEventPermissions.canSendMessage) { + if (timelineItem.isThreaded) { + add(TimelineItemAction.ReplyInThread) + } else { + add(TimelineItemAction.Reply) + } + } + if (timelineItem.isRemote && timelineItem.content.canBeForwarded()) { + add(TimelineItemAction.Forward) + } + if (timelineItem.isEditable) { + add(TimelineItemAction.Edit) + } + if (canRedact && timelineItem.content is TimelineItemPollContent && !timelineItem.content.isEnded) { + add(TimelineItemAction.EndPoll) + } + if (timelineItem.content.canBeCopied()) { + add(TimelineItemAction.Copy) + } + if (timelineItem.isRemote) { + add(TimelineItemAction.CopyLink) + } + if (isDeveloperModeEnabled) { + add(TimelineItemAction.ViewSource) + } + if (!timelineItem.isMine) { + add(TimelineItemAction.ReportContent) + } + if (canRedact) { + add(TimelineItemAction.Redact) + } + }.postFilter(timelineItem.content) +} + +/** + * Post filter the actions based on the content of the event. + */ +private fun List.postFilter(content: TimelineItemEventContent): List { + return filter { action -> + when (content) { + is TimelineItemCallNotifyContent, + is TimelineItemLegacyCallInviteContent, + is TimelineItemStateContent, + is TimelineItemRedactedContent -> { + action == TimelineItemAction.ViewSource + } + else -> true + } + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index f6b58e2799..55a82fa791 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -127,6 +127,7 @@ internal fun aTimelineItemEvent( transactionId: TransactionId? = null, isMine: Boolean = false, isEditable: Boolean = false, + canBeRepliedTo: Boolean = false, senderDisplayName: String = "Sender", displayNameAmbiguous: Boolean = false, content: TimelineItemEventContent = aTimelineItemTextContent(), @@ -150,6 +151,7 @@ internal fun aTimelineItemEvent( sentTime = "12:34", isMine = isMine, isEditable = isEditable, + canBeRepliedTo = canBeRepliedTo, senderProfile = aProfileTimelineDetailsReady( displayName = senderDisplayName, displayNameAmbiguous = displayNameAmbiguous, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index a2ac0ac7b1..528217d367 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -77,7 +77,6 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent -import io.element.android.features.messages.impl.timeline.model.event.canBeRepliedTo import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.components.EqualWidthColumn import io.element.android.libraries.designsystem.components.avatar.Avatar @@ -148,7 +147,7 @@ fun TimelineItemEventRow( } else { Spacer(modifier = Modifier.height(2.dp)) } - val canReply = timelineRoomInfo.userHasPermissionToSendMessage && event.content.canBeRepliedTo() + val canReply = timelineRoomInfo.userHasPermissionToSendMessage && event.canBeRepliedTo if (canReply) { val state: SwipeableActionsState = rememberSwipeableActionsState() val offset = state.offset.floatValue diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt index c5d303b3f1..3992c3304e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt @@ -76,6 +76,7 @@ class TimelineItemEventFactory @Inject constructor( content = contentFactory.create(currentTimelineItem.event), isMine = currentTimelineItem.event.isOwn, isEditable = currentTimelineItem.event.isEditable, + canBeRepliedTo = currentTimelineItem.event.canBeRepliedTo, sentTime = sentTime, groupPosition = groupPosition, reactionsState = currentTimelineItem.computeReactionsState(), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt index f77db70506..2ebb1bac24 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt @@ -18,6 +18,7 @@ package io.element.android.features.messages.impl.timeline.model import androidx.compose.runtime.Immutable import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemVirtualModel @@ -74,6 +75,7 @@ sealed interface TimelineItem { val sentTime: String = "", val isMine: Boolean = false, val isEditable: Boolean, + val canBeRepliedTo: Boolean, val groupPosition: TimelineItemGroupPosition = TimelineItemGroupPosition.None, val reactionsState: TimelineItemReactions, val readReceiptState: TimelineItemReadReceipts, @@ -94,6 +96,7 @@ sealed interface TimelineItem { val isSticker: Boolean = content is TimelineItemStickerContent val isRemote = eventId != null + } @Immutable diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt index 43fb947433..5a52f476f1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt @@ -24,27 +24,27 @@ sealed interface TimelineItemEventContent { } /** - * Only text based content and states can be copied. + * Only text based content can be copied. */ fun TimelineItemEventContent.canBeCopied(): Boolean = - when (this) { - is TimelineItemTextBasedContent, - is TimelineItemStateContent, - is TimelineItemRedactedContent -> true - else -> false - } + this is TimelineItemTextBasedContent /** - * Determine if the event content can be replied to. - * Note: it should match the logic in [io.element.android.features.messages.impl.actionlist.ActionListPresenter]. + * Returns true if the event content can be forwarded. */ -fun TimelineItemEventContent.canBeRepliedTo(): Boolean = +fun TimelineItemEventContent.canBeForwarded(): Boolean = when (this) { - is TimelineItemRedactedContent, - is TimelineItemLegacyCallInviteContent, - is TimelineItemCallNotifyContent, - is TimelineItemStateContent -> false - else -> true + is TimelineItemTextBasedContent, + is TimelineItemImageContent, + is TimelineItemFileContent, + is TimelineItemAudioContent, + is TimelineItemVideoContent, + is TimelineItemLocationContent, + is TimelineItemVoiceContent -> true + // Stickers can't be forwarded (yet) so we don't show the option + // See https://github.com/element-hq/element-x-android/issues/2161 + is TimelineItemStickerContent -> false + else -> false } /** 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 091305893e..6b06adeb03 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 @@ -137,8 +137,8 @@ class MessagesPresenterTest { assertThat(initialState.roomName).isEqualTo(AsyncData.Success("")) assertThat(initialState.roomAvatar) .isEqualTo(AsyncData.Success(AvatarData(id = A_ROOM_ID.value, name = "", url = AN_AVATAR_URL, size = AvatarSize.TimelineRoom))) - assertThat(initialState.userHasPermissionToSendMessage).isTrue() - assertThat(initialState.userHasPermissionToRedactOwn).isTrue() + assertThat(initialState.userEventPermissions.canSendMessage).isTrue() + assertThat(initialState.userEventPermissions.canRedactOwn).isTrue() assertThat(initialState.hasNetworkConnection).isTrue() assertThat(initialState.snackbarMessage).isNull() assertThat(initialState.inviteProgress).isEqualTo(AsyncData.Uninitialized) @@ -787,7 +787,7 @@ class MessagesPresenterTest { presenter.present() }.test { val state = awaitFirstItem() - assertThat(state.userHasPermissionToSendMessage).isTrue() + assertThat(state.userEventPermissions.canSendMessage).isTrue() } } @@ -811,9 +811,9 @@ class MessagesPresenterTest { presenter.present() }.test { // Default value - assertThat(awaitItem().userHasPermissionToSendMessage).isTrue() + assertThat(awaitItem().userEventPermissions.canSendMessage).isTrue() skipItems(1) - assertThat(awaitItem().userHasPermissionToSendMessage).isFalse() + assertThat(awaitItem().userEventPermissions.canSendMessage).isFalse() cancelAndIgnoreRemainingEvents() } } @@ -831,9 +831,9 @@ class MessagesPresenterTest { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - val initialState = consumeItemsUntilPredicate { it.userHasPermissionToRedactOwn }.last() - assertThat(initialState.userHasPermissionToRedactOwn).isTrue() - assertThat(initialState.userHasPermissionToRedactOther).isFalse() + val initialState = consumeItemsUntilPredicate { it.userEventPermissions.canRedactOwn }.last() + assertThat(initialState.userEventPermissions.canRedactOwn).isTrue() + assertThat(initialState.userEventPermissions.canRedactOther).isFalse() cancelAndIgnoreRemainingEvents() } } @@ -851,9 +851,9 @@ class MessagesPresenterTest { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - val initialState = consumeItemsUntilPredicate { it.userHasPermissionToRedactOther }.last() - assertThat(initialState.userHasPermissionToRedactOwn).isFalse() - assertThat(initialState.userHasPermissionToRedactOther).isTrue() + val initialState = consumeItemsUntilPredicate { it.userEventPermissions.canRedactOther }.last() + assertThat(initialState.userEventPermissions.canRedactOwn).isFalse() + assertThat(initialState.userEventPermissions.canRedactOther).isTrue() cancelAndIgnoreRemainingEvents() } } @@ -963,6 +963,7 @@ class MessagesPresenterTest { room = matrixRoom, sessionPreferencesStore = sessionPreferencesStore, ) + val readReceiptBottomSheetPresenter = ReadReceiptBottomSheetPresenter() val customReactionPresenter = CustomReactionPresenter(emojibaseProvider = FakeEmojibaseProvider()) val reactionSummaryPresenter = ReactionSummaryPresenter(room = matrixRoom) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index 9a22ced505..446c36f74c 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -26,6 +26,7 @@ import androidx.compose.ui.test.onAllNodesWithContentDescription import androidx.compose.ui.test.onAllNodesWithTag import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onFirst +import androidx.compose.ui.test.onLast import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText @@ -43,7 +44,6 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState import io.element.android.features.messages.impl.timeline.aTimelineItemEvent -import io.element.android.features.messages.impl.timeline.aTimelineItemList import io.element.android.features.messages.impl.timeline.aTimelineItemReadReceipts import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo import io.element.android.features.messages.impl.timeline.aTimelineState @@ -175,10 +175,12 @@ class MessagesViewTest { actionListState = anActionListState( eventSink = eventsRecorder ), - userHasPermissionToSendMessage = userHasPermissionToSendMessage, - userHasPermissionToRedactOwn = userHasPermissionToRedactOwn, - userHasPermissionToRedactOther = userHasPermissionToRedactOther, - userHasPermissionToSendReaction = userHasPermissionToSendReaction, + userEventPermissions = UserEventPermissions( + canSendMessage = userHasPermissionToSendMessage, + canRedactOwn = userHasPermissionToRedactOwn, + canRedactOther = userHasPermissionToRedactOther, + canSendReaction = userHasPermissionToSendReaction, + ), ) val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event rule.setMessagesView( @@ -189,10 +191,7 @@ class MessagesViewTest { eventsRecorder.assertSingle( ActionListEvents.ComputeForMessage( event = timelineItem, - canRedactOwn = state.userHasPermissionToRedactOwn, - canRedactOther = state.userHasPermissionToRedactOther, - canSendMessage = state.userHasPermissionToSendMessage, - canSendReaction = state.userHasPermissionToSendReaction, + userEventPermissions = state.userEventPermissions, ) ) } @@ -237,9 +236,11 @@ class MessagesViewTest { private fun swipeTest(userHasPermissionToSendMessage: Boolean) { val eventsRecorder = EventsRecorder() + val canBeRepliedEvent = aTimelineItemEvent(canBeRepliedTo = true) + val cannotBeRepliedEvent = aTimelineItemEvent(canBeRepliedTo = false) val state = aMessagesState( timelineState = aTimelineState( - timelineItems = aTimelineItemList(aTimelineItemTextContent()), + timelineItems = persistentListOf(canBeRepliedEvent, cannotBeRepliedEvent), timelineRoomInfo = aTimelineRoomInfo( userHasPermissionToSendMessage = userHasPermissionToSendMessage ), @@ -249,10 +250,12 @@ class MessagesViewTest { rule.setMessagesView( state = state, ) - rule.onAllNodesWithTag(TestTags.messageBubble.value).onFirst().performTouchInput { swipeRight(endX = 200f) } + rule.onAllNodesWithTag(TestTags.messageBubble.value).apply { + onFirst().performTouchInput { swipeRight(endX = 200f) } + onLast().performTouchInput { swipeRight(endX = 200f) } + } if (userHasPermissionToSendMessage) { - val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event - eventsRecorder.assertSingle(MessagesEvents.HandleAction(TimelineItemAction.Reply, timelineItem)) + eventsRecorder.assertSingle(MessagesEvents.HandleAction(TimelineItemAction.Reply, canBeRepliedEvent)) } else { eventsRecorder.assertEmpty() } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt index 76c43a9c8b..716c133c0a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt @@ -20,6 +20,7 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.features.messages.impl.aUserEventPermissions import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.timeline.aTimelineItemEvent @@ -31,6 +32,7 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent import io.element.android.features.poll.api.pollcontent.aPollAnswerItemList +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.test.A_MESSAGE import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.tests.testutils.WarmUpRule @@ -66,10 +68,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = false, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = false, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) // val loadingState = awaitItem() @@ -104,10 +108,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = false, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = false, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) // val loadingState = awaitItem() @@ -142,10 +148,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = false, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = false, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) // val loadingState = awaitItem() @@ -185,10 +193,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = true, - canRedactOther = false, - canSendMessage = false, - canSendReaction = true + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = false, + canSendReaction = true + ) ) ) // val loadingState = awaitItem() @@ -227,10 +237,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = false, - canRedactOther = true, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = false, + canRedactOther = true, + canSendMessage = true, + canSendReaction = true, + ) ) ) val successState = awaitItem() @@ -269,10 +281,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = false, - canRedactOther = true, - canSendMessage = true, - canSendReaction = false + userEventPermissions = aUserEventPermissions( + canRedactOwn = false, + canRedactOther = true, + canSendMessage = true, + canSendReaction = false + ) ) ) val successState = awaitItem() @@ -310,10 +324,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = true, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) // val loadingState = awaitItem() @@ -353,10 +369,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = false, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = false, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) // val loadingState = awaitItem() @@ -396,10 +414,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = true, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ), ) ) // val loadingState = awaitItem() @@ -437,10 +457,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = stateEvent, - canRedactOwn = false, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = false, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) // val loadingState = awaitItem() @@ -451,8 +473,6 @@ class ActionListPresenterTest { event = stateEvent, displayEmojiReactions = false, actions = persistentListOf( - TimelineItemAction.Copy, - TimelineItemAction.CopyLink, TimelineItemAction.ViewSource, ) ) @@ -476,26 +496,16 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = stateEvent, - canRedactOwn = false, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = false, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) // val loadingState = awaitItem() // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) - val successState = awaitItem() - assertThat(successState.target).isEqualTo( - ActionListState.Target.Success( - event = stateEvent, - displayEmojiReactions = false, - actions = persistentListOf( - TimelineItemAction.Copy, - TimelineItemAction.CopyLink, - ) - ) - ) - initialState.eventSink.invoke(ActionListEvents.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -514,10 +524,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = true, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) // val loadingState = awaitItem() @@ -561,10 +573,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = false, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = false, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) assertThat(awaitItem().target).isInstanceOf(ActionListState.Target.Success::class.java) @@ -572,10 +586,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = redactedEvent, - canRedactOwn = false, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = false, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) awaitItem().run { @@ -595,16 +611,19 @@ class ActionListPresenterTest { // No event id, so it's not sent yet eventId = null, isMine = true, + canBeRepliedTo = false, content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = null), ) initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = true, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) val successState = awaitItem() @@ -637,10 +656,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = true, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) val successState = awaitItem() @@ -675,10 +696,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = true, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) val successState = awaitItem() @@ -712,10 +735,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = true, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) val successState = awaitItem() @@ -742,15 +767,18 @@ class ActionListPresenterTest { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, + isEditable = false, content = aTimelineItemVoiceContent(), ) initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = true, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) val successState = awaitItem() @@ -783,10 +811,12 @@ class ActionListPresenterTest { initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( event = messageEvent, - canRedactOwn = true, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + ) ) ) val successState = awaitItem() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt index 7f2c3cfbeb..ca805d44c7 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt @@ -42,6 +42,7 @@ internal fun aMessageEvent( transactionId: TransactionId? = null, isMine: Boolean = true, isEditable: Boolean = true, + canBeRepliedTo: Boolean = true, content: TimelineItemEventContent = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, formattedBody = null, isEdited = false), inReplyTo: InReplyToDetails? = null, isThreaded: Boolean = false, @@ -58,6 +59,7 @@ internal fun aMessageEvent( sentTime = "", isMine = isMine, isEditable = isEditable, + canBeRepliedTo = canBeRepliedTo, reactionsState = aTimelineItemReactions(count = 0), readReceiptState = TimelineItemReadReceipts(emptyList().toImmutableList()), localSendState = sendState, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt index ce53e05090..e044ac7e2b 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt @@ -46,6 +46,7 @@ class TimelineItemGrouperTest { readReceiptState = TimelineItemReadReceipts(emptyList().toImmutableList()), localSendState = LocalEventSendState.Sent(AN_EVENT_ID), isEditable = false, + canBeRepliedTo = false, inReplyTo = null, isThreaded = false, debugInfo = aTimelineItemDebugInfo(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt index 4cabc6450a..2a54edad58 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt @@ -85,6 +85,7 @@ fun aRedactedMatrixTimeline(eventId: EventId) = listOf( eventId = eventId, transactionId = null, isEditable = false, + canBeRepliedTo = false, isLocal = false, isOwn = false, isRemote = false, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt index fa15f8f096..4a8f330c5c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt @@ -26,6 +26,7 @@ data class EventTimelineItem( val eventId: EventId?, val transactionId: TransactionId?, val isEditable: Boolean, + val canBeRepliedTo: Boolean, val isLocal: Boolean, val isOwn: Boolean, val isRemote: Boolean, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt index dd0bdabd7f..2ae0a3e909 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt @@ -44,6 +44,7 @@ class EventTimelineItemMapper(private val contentMapper: TimelineEventContentMap eventId = it.eventId()?.let(::EventId), transactionId = it.transactionId()?.let(::TransactionId), isEditable = it.isEditable(), + canBeRepliedTo = it.canBeRepliedTo(), isLocal = it.isLocal(), isOwn = it.isOwn(), isRemote = it.isRemote(), diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt index d53bc7b18f..f9e9efb210 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt @@ -46,6 +46,7 @@ fun anEventTimelineItem( eventId: EventId = AN_EVENT_ID, transactionId: TransactionId? = null, isEditable: Boolean = false, + canBeRepliedTo: Boolean = false, isLocal: Boolean = false, isOwn: Boolean = false, isRemote: Boolean = false, @@ -61,6 +62,7 @@ fun anEventTimelineItem( eventId = eventId, transactionId = transactionId, isEditable = isEditable, + canBeRepliedTo = canBeRepliedTo, isLocal = isLocal, isOwn = isOwn, isRemote = isRemote, From c9a89c77ef9c5e7d91ad3ac071d3be0f54b4ce06 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 26 Jul 2024 18:20:17 +0200 Subject: [PATCH 024/186] Pinned event: add action on timeline --- .../features/messages/impl/MessagesPresenter.kt | 2 ++ .../features/messages/impl/MessagesStateProvider.kt | 2 ++ .../features/messages/impl/UserEventPermissions.kt | 1 + .../messages/impl/actionlist/ActionListPresenter.kt | 13 +++++++++++++ .../impl/actionlist/model/TimelineItemAction.kt | 1 + .../features/messages/impl/MessagesPresenterTest.kt | 5 +++-- .../features/messages/impl/MessagesViewTest.kt | 2 ++ .../impl/actionlist/ActionListPresenterTest.kt | 3 ++- 8 files changed, 26 insertions(+), 3 deletions(-) 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 2a1ea9dd51..16698d7e34 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 @@ -245,6 +245,7 @@ class MessagesPresenter @AssistedInject constructor( canRedactOwn = userHasPermissionToRedactOwn, canRedactOther = userHasPermissionToRedactOther, canSendReaction = userHasPermissionToSendReaction, + canPin = false, ) } } @@ -283,6 +284,7 @@ class MessagesPresenter @AssistedInject constructor( TimelineItemAction.Forward -> handleForwardAction(targetEvent) TimelineItemAction.ReportContent -> handleReportAction(targetEvent) TimelineItemAction.EndPoll -> handleEndPollAction(targetEvent, timelineState) + TimelineItemAction.Pin -> Timber.d("Pin action not implemented") } } 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 082edb1ca3..61f2189cc6 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 @@ -144,11 +144,13 @@ fun aUserEventPermissions( canRedactOther: Boolean = false, canSendMessage: Boolean = true, canSendReaction: Boolean = true, + canPin: Boolean = false, ) = UserEventPermissions( canRedactOwn = canRedactOwn, canRedactOther = canRedactOther, canSendMessage = canSendMessage, canSendReaction = canSendReaction, + canPin = canPin, ) fun aReactionSummaryState( 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 84b60ae228..c75054be3a 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 @@ -25,4 +25,5 @@ data class UserEventPermissions( val canRedactOther: Boolean, val canSendMessage: Boolean, val canSendReaction: Boolean, + val canPin: Boolean, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index 0f4379cffb..3387373734 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -36,6 +36,8 @@ import io.element.android.features.messages.impl.timeline.model.event.canBeCopie import io.element.android.features.messages.impl.timeline.model.event.canBeForwarded import io.element.android.features.messages.impl.timeline.model.event.canReact 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.preferences.api.store.AppPreferencesStore import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope @@ -44,6 +46,7 @@ import javax.inject.Inject class ActionListPresenter @Inject constructor( private val appPreferencesStore: AppPreferencesStore, + private val featureFlagsService: FeatureFlagService, ) : Presenter { @Composable override fun present(): ActionListState { @@ -54,6 +57,7 @@ class ActionListPresenter @Inject constructor( } val isDeveloperModeEnabled by appPreferencesStore.isDeveloperModeEnabledFlow().collectAsState(initial = false) + val isPinnedEventsEnabled by featureFlagsService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false) fun handleEvents(event: ActionListEvents) { when (event) { @@ -62,6 +66,7 @@ class ActionListPresenter @Inject constructor( timelineItem = event.event, usersEventPermissions = event.userEventPermissions, isDeveloperModeEnabled = isDeveloperModeEnabled, + isPinnedEventsEnabled = isPinnedEventsEnabled, target = target, ) } @@ -77,6 +82,7 @@ class ActionListPresenter @Inject constructor( timelineItem: TimelineItem.Event, usersEventPermissions: UserEventPermissions, isDeveloperModeEnabled: Boolean, + isPinnedEventsEnabled: Boolean, target: MutableState ) = launch { target.value = ActionListState.Target.Loading(timelineItem) @@ -85,6 +91,7 @@ class ActionListPresenter @Inject constructor( timelineItem = timelineItem, usersEventPermissions = usersEventPermissions, isDeveloperModeEnabled = isDeveloperModeEnabled, + isPinnedEventsEnabled = isPinnedEventsEnabled, ) val displayEmojiReactions = usersEventPermissions.canSendReaction && timelineItem.isRemote && @@ -105,6 +112,7 @@ private fun buildActions( timelineItem: TimelineItem.Event, usersEventPermissions: UserEventPermissions, isDeveloperModeEnabled: Boolean, + isPinnedEventsEnabled: Boolean, ): List { val canRedact = timelineItem.isMine && usersEventPermissions.canRedactOwn || !timelineItem.isMine && usersEventPermissions.canRedactOther return buildList { @@ -124,6 +132,11 @@ private fun buildActions( if (canRedact && timelineItem.content is TimelineItemPollContent && !timelineItem.content.isEnded) { add(TimelineItemAction.EndPoll) } + // TODO: handle unpin + val canPin = isPinnedEventsEnabled && usersEventPermissions.canPin && timelineItem.isRemote + if (canPin) { + add(TimelineItemAction.Pin) + } if (timelineItem.content.canBeCopied()) { add(TimelineItemAction.Copy) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt index f61e6197c2..e8da131d8d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt @@ -39,4 +39,5 @@ sealed class TimelineItemAction( data object ViewSource : TimelineItemAction(CommonStrings.action_view_source, CommonDrawables.ic_developer_options) data object ReportContent : TimelineItemAction(CommonStrings.action_report_content, CompoundDrawables.ic_compound_chat_problem, destructive = true) data object EndPoll : TimelineItemAction(CommonStrings.action_end_poll, CompoundDrawables.ic_compound_polls_end) + data object Pin : TimelineItemAction(CommonStrings.action_pin, CompoundDrawables.ic_compound_pin) } 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 6b06adeb03..74eccd00ca 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 @@ -958,7 +958,8 @@ class MessagesPresenterTest { return timelinePresenter } } - val actionListPresenter = ActionListPresenter(appPreferencesStore = appPreferencesStore) + val featureFlagService = FakeFeatureFlagService() + val actionListPresenter = ActionListPresenter(appPreferencesStore = appPreferencesStore, featureFlagsService = featureFlagService) val typingNotificationPresenter = TypingNotificationPresenter( room = matrixRoom, sessionPreferencesStore = sessionPreferencesStore, @@ -981,7 +982,7 @@ class MessagesPresenterTest { snackbarDispatcher = SnackbarDispatcher(), navigator = navigator, clipboardHelper = clipboardHelper, - featureFlagsService = FakeFeatureFlagService(), + featureFlagsService = featureFlagService, buildMeta = aBuildMeta(), dispatchers = coroutineDispatchers, htmlConverterProvider = FakeHtmlConverterProvider(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index 446c36f74c..17a051ba9b 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -169,6 +169,7 @@ class MessagesViewTest { userHasPermissionToRedactOwn: Boolean = false, userHasPermissionToRedactOther: Boolean = false, userHasPermissionToSendReaction: Boolean = false, + userCanPinEvent: Boolean = false, ) { val eventsRecorder = EventsRecorder() val state = aMessagesState( @@ -180,6 +181,7 @@ class MessagesViewTest { canRedactOwn = userHasPermissionToRedactOwn, canRedactOther = userHasPermissionToRedactOther, canSendReaction = userHasPermissionToSendReaction, + canPin = userCanPinEvent, ), ) val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt index 716c133c0a..5bd16bfe61 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt @@ -835,5 +835,6 @@ class ActionListPresenterTest { private fun createActionListPresenter(isDeveloperModeEnabled: Boolean): ActionListPresenter { val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled) - return ActionListPresenter(appPreferencesStore = preferencesStore) + val featureFlagsService = FakeFeatureFlagService() + return ActionListPresenter(appPreferencesStore = preferencesStore, featureFlagsService = featureFlagsService) } From b7e843a00abbbe25caa72e4faefdee15e1cb4662 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 27 Jul 2024 16:38:59 +0000 Subject: [PATCH 025/186] Update dependency org.matrix.rustcomponents:sdk-android to v0.2.35 --- 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 0609a17dc2..dc6ab7d532 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.34" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.35" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From 76804d9e48b107cc8adb2adb66066b61de0f5499 Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 29 Jul 2024 00:26:27 +0000 Subject: [PATCH 026/186] Sync Strings from Localazy --- app/src/main/res/xml/locales_config.xml | 1 + .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-uz/translations.xml | 7 + .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-uz/translations.xml | 10 + .../src/main/res/values-pl/translations.xml | 1 + .../src/main/res/values-uz/translations.xml | 6 + .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-uz/translations.xml | 14 + .../src/main/res/values-uz/translations.xml | 11 + .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-uz/translations.xml | 9 + .../src/main/res/values-pl/translations.xml | 11 + .../src/main/res/values-uz/translations.xml | 6 + .../src/main/res/values-pl/translations.xml | 6 +- .../main/res/values-pt-rBR/translations.xml | 17 +- .../src/main/res/values-uz/translations.xml | 4 + .../src/main/res/values-pl/translations.xml | 48 +- .../src/main/res/values-uz/translations.xml | 42 + .../main/res/values-pt-rBR/translations.xml | 4 + .../src/main/res/values-uz/translations.xml | 8 + .../src/main/res/values-pl/translations.xml | 12 +- .../main/res/values-pt-rBR/translations.xml | 14 +- .../src/main/res/values-uz/translations.xml | 42 + .../main/res/values-pt-rBR/translations.xml | 1 + .../src/main/res/values-uz/translations.xml | 9 + .../main/res/values-pt-rBR/translations.xml | 6 + .../src/main/res/values-uz/translations.xml | 11 + .../src/main/res/values-pl/translations.xml | 13 +- .../main/res/values-pt-rBR/translations.xml | 9 + .../src/main/res/values-uz/translations.xml | 42 + .../src/main/res/values-uz/translations.xml | 7 + .../src/main/res/values-pl/translations.xml | 3 +- .../main/res/values-pt-rBR/translations.xml | 1 + .../src/main/res/values-uz/translations.xml | 15 + .../src/main/res/values-pl/translations.xml | 4 + .../src/main/res/values-pl/translations.xml | 67 + .../main/res/values-pt-rBR/translations.xml | 51 + .../src/main/res/values-uz/translations.xml | 45 + .../src/main/res/values-pl/translations.xml | 5 + .../main/res/values-pt-rBR/translations.xml | 4 + .../src/main/res/values-pl/translations.xml | 22 +- .../main/res/values-pt-rBR/translations.xml | 13 + .../src/main/res/values-uz/translations.xml | 18 + .../src/main/res/values-pl/translations.xml | 14 +- .../main/res/values-pt-rBR/translations.xml | 5 +- .../src/main/res/values-uz/translations.xml | 40 + .../src/main/res/values-uz/translations.xml | 8 + .../src/main/res/values-uz/translations.xml | 10 + .../src/main/res/values-pl/translations.xml | 10 +- .../main/res/values-pt-rBR/translations.xml | 6 + .../src/main/res/values-uz/translations.xml | 17 + .../src/main/res/values-uz/translations.xml | 4 + .../src/main/res/values-pl/translations.xml | 6 +- .../main/res/values-pt-rBR/translations.xml | 6 + .../src/main/res/values-uz/translations.xml | 57 + .../src/main/res/values-uz/translations.xml | 4 + .../src/main/res/values-uz/translations.xml | 7 + .../src/main/res/values-pl/translations.xml | 5 + .../src/main/res/values-pl/translations.xml | 26 + .../main/res/values-pt-rBR/translations.xml | 2 + .../src/main/res/values-uz/translations.xml | 50 + .../src/main/res/values-pl/translations.xml | 11 + .../src/main/res/values-pl/translations.xml | 11 + .../src/main/res/values-pl/translations.xml | 14 +- .../main/res/values-pt-rBR/translations.xml | 2 + .../src/main/res/values-uz/translations.xml | 25 + .../src/main/res/values-pl/translations.xml | 11 + .../src/main/res/values-be/translations.xml | 3 + .../src/main/res/values-cs/translations.xml | 9 + .../src/main/res/values-el/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 8 +- .../main/res/values-pt-rBR/translations.xml | 15 +- .../src/main/res/values-ru/translations.xml | 10 + .../src/main/res/values-sk/translations.xml | 1 + .../src/main/res/values-uz/translations.xml | 210 +++ .../src/main/res/values/localazy.xml | 1 + plugins/src/main/kotlin/extension/locales.kt | 1 + ...es.joinroom.impl_JoinRoomView_Day_1_de.png | 4 +- ...veloper_DeveloperSettingsView_Day_0_de.png | 4 +- ...veloper_DeveloperSettingsView_Day_1_de.png | 4 +- ...veloper_DeveloperSettingsView_Day_2_de.png | 4 +- screenshots/html/data.js | 1128 ++++++++--------- 84 files changed, 1774 insertions(+), 608 deletions(-) create mode 100644 features/analytics/api/src/main/res/values-uz/translations.xml create mode 100644 features/analytics/impl/src/main/res/values-uz/translations.xml create mode 100644 features/call/impl/src/main/res/values-uz/translations.xml create mode 100644 features/createroom/impl/src/main/res/values-uz/translations.xml create mode 100644 features/ftue/impl/src/main/res/values-uz/translations.xml create mode 100644 features/invite/impl/src/main/res/values-uz/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-pl/translations.xml create mode 100644 features/leaveroom/api/src/main/res/values-uz/translations.xml create mode 100644 features/lockscreen/impl/src/main/res/values-uz/translations.xml create mode 100644 features/login/impl/src/main/res/values-uz/translations.xml create mode 100644 features/logout/impl/src/main/res/values-uz/translations.xml create mode 100644 features/messages/impl/src/main/res/values-uz/translations.xml create mode 100644 features/onboarding/impl/src/main/res/values-uz/translations.xml create mode 100644 features/poll/impl/src/main/res/values-uz/translations.xml create mode 100644 features/preferences/impl/src/main/res/values-uz/translations.xml create mode 100644 features/rageshake/api/src/main/res/values-uz/translations.xml create mode 100644 features/rageshake/impl/src/main/res/values-uz/translations.xml create mode 100644 features/roomaliasresolver/impl/src/main/res/values-pl/translations.xml create mode 100644 features/roomdetails/impl/src/main/res/values-uz/translations.xml create mode 100644 features/roomdirectory/impl/src/main/res/values-pl/translations.xml create mode 100644 features/roomdirectory/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/roomlist/impl/src/main/res/values-uz/translations.xml create mode 100644 features/securebackup/impl/src/main/res/values-uz/translations.xml create mode 100644 features/signedout/impl/src/main/res/values-uz/translations.xml create mode 100644 features/userprofile/shared/src/main/res/values-uz/translations.xml create mode 100644 features/verifysession/impl/src/main/res/values-uz/translations.xml create mode 100644 libraries/androidutils/src/main/res/values-uz/translations.xml create mode 100644 libraries/eventformatter/impl/src/main/res/values-uz/translations.xml create mode 100644 libraries/matrixui/src/main/res/values-uz/translations.xml create mode 100644 libraries/permissions/api/src/main/res/values-uz/translations.xml create mode 100644 libraries/permissions/impl/src/main/res/values-pl/translations.xml create mode 100644 libraries/push/impl/src/main/res/values-uz/translations.xml create mode 100644 libraries/pushproviders/firebase/src/main/res/values-pl/translations.xml create mode 100644 libraries/pushproviders/unifiedpush/src/main/res/values-pl/translations.xml create mode 100644 libraries/textcomposer/impl/src/main/res/values-uz/translations.xml create mode 100644 libraries/troubleshoot/impl/src/main/res/values-pl/translations.xml create mode 100644 libraries/ui-strings/src/main/res/values-uz/translations.xml diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml index fa0e1e2199..e49aa1e4a0 100644 --- a/app/src/main/res/xml/locales_config.xml +++ b/app/src/main/res/xml/locales_config.xml @@ -21,6 +21,7 @@ + diff --git a/features/analytics/api/src/main/res/values-pl/translations.xml b/features/analytics/api/src/main/res/values-pl/translations.xml index 26aa9c6073..9fd1f51683 100644 --- a/features/analytics/api/src/main/res/values-pl/translations.xml +++ b/features/analytics/api/src/main/res/values-pl/translations.xml @@ -1,7 +1,7 @@ "Udostępniaj anonimowe dane dotyczące użytkowania, aby pomóc nam identyfikować problemy." - "Możesz przeczytać wszystkie nasze warunki %1$s." + "Przeczytaj nasze warunki użytkowania %1$s." "tutaj" "Udostępniaj dane analityczne" diff --git a/features/analytics/api/src/main/res/values-uz/translations.xml b/features/analytics/api/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..787a1b03bc --- /dev/null +++ b/features/analytics/api/src/main/res/values-uz/translations.xml @@ -0,0 +1,7 @@ + + + "Muammolarni aniqlashda yordam berish uchun anonim foydalanish maʼlumotlarini baham koʻring." + "Siz bizning barcha shartlarimizni o\'qishingiz mumkin%1$s." + "Bu yerga" + "Analitik ma\'lumotlarni ulashish" + diff --git a/features/analytics/impl/src/main/res/values-pl/translations.xml b/features/analytics/impl/src/main/res/values-pl/translations.xml index 99e3e441bb..02faba157f 100644 --- a/features/analytics/impl/src/main/res/values-pl/translations.xml +++ b/features/analytics/impl/src/main/res/values-pl/translations.xml @@ -2,7 +2,7 @@ "Nie będziemy rejestrować ani profilować żadnych danych osobistych" "Udostępniaj anonimowe dane dotyczące użytkowania, aby pomóc nam identyfikować problemy." - "Możesz przeczytać wszystkie nasze warunki %1$s." + "Przeczytaj nasze warunki użytkowania %1$s." "tutaj" "Możesz to wyłączyć w dowolnym momencie" "Nie będziemy udostępniać Twoich danych podmiotom trzecim" diff --git a/features/analytics/impl/src/main/res/values-uz/translations.xml b/features/analytics/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..daa1080628 --- /dev/null +++ b/features/analytics/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,10 @@ + + + "Biz hech qanday shaxsiy ma\'lumotlarni yozmaymiz yoki profilga kiritmaymiz" + "Muammolarni aniqlashda yordam berish uchun anonim foydalanish maʼlumotlarini baham koʻring." + "Siz bizning barcha shartlarimizni o\'qishingiz mumkin%1$s." + "Bu yerga" + "Buni istalgan vaqtda oʻchirib qoʻyishingiz mumkin" + "Biz sizning ma\'lumotlaringizni uchinchi tomonlar bilan baham ko\'rmaymiz" + "Yaxshilashga yordam bering%1$s" + diff --git a/features/call/impl/src/main/res/values-pl/translations.xml b/features/call/impl/src/main/res/values-pl/translations.xml index 27133cd91b..e63fc80d14 100644 --- a/features/call/impl/src/main/res/values-pl/translations.xml +++ b/features/call/impl/src/main/res/values-pl/translations.xml @@ -3,4 +3,5 @@ "Połączenie w trakcie" "Stuknij, aby wrócić do rozmowy" "☎️ Rozmowa w toku" + "Przychodzące połączenie Element" diff --git a/features/call/impl/src/main/res/values-uz/translations.xml b/features/call/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..010695a2ef --- /dev/null +++ b/features/call/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,6 @@ + + + "Davom etayotgan qo\'ng\'iroq" + "Qo\'ng\'iroqqa qaytish uchun bosing" + "☎️ Qo‘ng‘iroq davom etmoqda" + diff --git a/features/createroom/impl/src/main/res/values-pl/translations.xml b/features/createroom/impl/src/main/res/values-pl/translations.xml index eb64b46d8c..37090055b9 100644 --- a/features/createroom/impl/src/main/res/values-pl/translations.xml +++ b/features/createroom/impl/src/main/res/values-pl/translations.xml @@ -6,7 +6,7 @@ "Wiadomości w tym pokoju są szyfrowane. Szyfrowania nie można później wyłączyć." "Pokój prywatny (tylko zaproszenie)" "Wiadomości nie są szyfrowane i każdy może je odczytać. Możesz aktywować szyfrowanie później." - "Pokój publiczny (każdy)" + "Pokój publiczny (wszyscy)" "Nazwa pokoju" "Utwórz pokój" "Temat (opcjonalnie)" diff --git a/features/createroom/impl/src/main/res/values-uz/translations.xml b/features/createroom/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..649bdf8613 --- /dev/null +++ b/features/createroom/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,14 @@ + + + "Yangi xona" + "Odamlarni taklif qiling" + "Xonani yaratishda xatolik yuz berdi" + "Bu xonadagi xabarlar shifrlangan. Keyinchalik shifrlashni o‘chirib bo‘lmaydi." + "Shaxsiy xona (faqat taklif)" + "Xabarlar shifrlanmagan va har kim ularni o\'qiy oladi. Keyinchalik shifrlashni yoqishingiz mumkin." + "Jamoat xonasi (har kim)" + "Xona nomi" + "Xonani yaratish" + "Mavzu (ixtiyoriy)" + "Suhbatni boshlashda xatolik yuz berdi" + diff --git a/features/ftue/impl/src/main/res/values-uz/translations.xml b/features/ftue/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..f8ede2ecf4 --- /dev/null +++ b/features/ftue/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,11 @@ + + + "Sozlamalaringizni keyinroq o\'zgartirishingiz mumkin." + "Bildirishnomalarga ruxsat bering va hech qachon xabarni o\'tkazib yubormang" + "Qo\'ng\'iroqlar, so\'ro\'vlar, qidiruv va boshqalar shu yil oxirida qo\'shiladi." + "Shifrlangan xonalar uchun xabarlar tarixi hali mavjud emas." + "Biz sizdan eshitishni istardik, sozlamalar sahifasi orqali fikringizni bildiring." + "Qani ketdik!" + "Buni bilishingiz kerak:" + "%1$sga Xush kelibsiz!" + diff --git a/features/invite/impl/src/main/res/values-pl/translations.xml b/features/invite/impl/src/main/res/values-pl/translations.xml index e33b1ae106..95283e4cba 100644 --- a/features/invite/impl/src/main/res/values-pl/translations.xml +++ b/features/invite/impl/src/main/res/values-pl/translations.xml @@ -1,6 +1,6 @@ - "Czy na pewno chcesz odrzucić zaproszenie do dołączenia do %1$s?" + "Czy na pewno chcesz odrzucić zaproszenie dołączenia do %1$s?" "Odrzuć zaproszenie" "Czy na pewno chcesz odrzucić rozmowę prywatną z %1$s?" "Odrzuć czat" diff --git a/features/invite/impl/src/main/res/values-uz/translations.xml b/features/invite/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..78e3975700 --- /dev/null +++ b/features/invite/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,9 @@ + + + "Haqiqatan ham qo\'shilish taklifini rad qilmoqchimisiz%1$s ?" + "Taklifni rad etish" + "Haqiqatan ham bu shaxsiy chatni rad qilmoqchimisiz%1$s ?" + "Chatni rad etish" + "Takliflar yo\'q" + "%1$s(%2$s ) sizni taklif qildi" + diff --git a/features/joinroom/impl/src/main/res/values-pl/translations.xml b/features/joinroom/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..585169fa80 --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,11 @@ + + + "Dołącz do pokoju" + "Zapukaj, by dołączyć" + "%1$s jeszcze nie obsługuje przestrzeni. Uzyskaj dostęp do przestrzeni w wersji web." + "Przestrzenie nie są jeszcze obsługiwane" + "Kliknij przycisk poniżej, aby powiadomić administratora pokoju. Po zatwierdzeniu będziesz mógł dołączyć do rozmowy." + "Musisz być członkiem tego pokoju, aby wyświetlić historię wiadomości." + "Chcesz dołączyć do tego pokoju?" + "Podgląd nie jest dostępny" + diff --git a/features/leaveroom/api/src/main/res/values-uz/translations.xml b/features/leaveroom/api/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..59c111e2ac --- /dev/null +++ b/features/leaveroom/api/src/main/res/values-uz/translations.xml @@ -0,0 +1,6 @@ + + + "Bu xonani tark etmoqchi ekanligingizga ishonchingiz komilmi? Siz bu yerda yagona odamsiz. Agar siz tark etsangiz, kelajakda hech kim qo\'shila olmaydi, jumladan siz ham." + "Bu xonani tark etmoqchi ekanligingizga ishonchingiz komilmi? Bu xona ochiq emas va siz taklifsiz qayta qo‘shila olmaysiz." + "Xonani tark etmoqchi ekanligingizga ishonchingiz komilmi?" + diff --git a/features/lockscreen/impl/src/main/res/values-pl/translations.xml b/features/lockscreen/impl/src/main/res/values-pl/translations.xml index 1eb904b13e..134799b146 100644 --- a/features/lockscreen/impl/src/main/res/values-pl/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-pl/translations.xml @@ -16,11 +16,11 @@ "Potwierdź PIN" "Zablokuj %1$s, aby zwiększyć bezpieczeństwo swoich czatów. -Wybierz coś łatwego do zapamiętania. Jeśli zapomnisz tego PINU, zostaniesz wylogowany z aplikacji." - "Nie możesz wybrać tego PINU ze względów bezpieczeństwa" +Wybierz coś łatwego do zapamiętania. Jeśli zapomnisz tego PIN\'u, zostaniesz wylogowany z aplikacji." + "Nie możesz wybrać tego PIN\'u ze względów bezpieczeństwa" "Wybierz inny kod PIN" "Wprowadź ten sam kod PIN dwa razy" - "PINY nie pasują do siebie" + "PIN\'y nie pasują do siebie" "Aby kontynuować, zaloguj się ponownie i utwórz nowy kod PIN" "Trwa wylogowywanie" diff --git a/features/lockscreen/impl/src/main/res/values-pt-rBR/translations.xml b/features/lockscreen/impl/src/main/res/values-pt-rBR/translations.xml index b7af1aba25..da8b201b6d 100644 --- a/features/lockscreen/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-pt-rBR/translations.xml @@ -1,14 +1,27 @@ + "autenticação por biometria" + "desbloqueio por biometria" + "Desbloquear com biometria" "Esqueceu o PIN?" - "Mudar código de PIN" + "Alterar código de PIN" "Permitir desbloqueio biométrico" "Remover PIN" "Tem certeza de que quer remover o PIN?" "Remover PIN?" + "Permitir %1$s" + "Prefiro usar o PIN" + "Poupe tempo e use %1$s para desbloquear o aplicativo todas as vezes" "Escolher PIN" "Confirmar PIN" + "Bloqueie o %1$s para adicionar uma segurança extra às suas conversas. + +Escolha algo memorável. Se você esquecer este PIN, você será desconectado do app." + "Você não pode escolher este PIN por razões de segurança" + "Escolha um PIN diferente" + "Por favor, insira o mesmo PIN duas vezes" "Os PINs não correspondem" + "Você terá que fazer login novamente e criar um novo PIN para prosseguir" "Você está sendo desconectado" "Você tem %1$d tentativa de debloqueio" @@ -18,5 +31,7 @@ "PIN incorreto. Você tem mais %1$d chance" "PIN incorreto. Você tem mais %1$d chances" + "Usar biometria" + "Usar PIN" "Saindo…" diff --git a/features/lockscreen/impl/src/main/res/values-uz/translations.xml b/features/lockscreen/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..b9f1c4f5cb --- /dev/null +++ b/features/lockscreen/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,4 @@ + + + "Chiqish…" + diff --git a/features/login/impl/src/main/res/values-pl/translations.xml b/features/login/impl/src/main/res/values-pl/translations.xml index 8adfbcb8a8..4d23e15fe8 100644 --- a/features/login/impl/src/main/res/values-pl/translations.xml +++ b/features/login/impl/src/main/res/values-pl/translations.xml @@ -6,7 +6,7 @@ "Szukaj serwera firmowego, społeczności lub prywatnego." "Znajdź dostawcę konta" "Tutaj będą przechowywane Twoje konwersacje - w podobnej formie jak wiadomości widnieją na skrzynce e-mail." - "Zamierzasz się zalogować %s" + "Zamierzasz zalogować się do %s" "Tutaj będą przechowywane Twoje konwersacje - w podobnej formie jak wiadomości widnieją na skrzynce e-mail." "Zamierzasz założyć konto na %s" "Matrix.org jest ogromnym i darmowym serwerem na publicznej sieci Matrix zapewniający bezpieczną i zdecentralizowaną komunikację zarządzaną przez Fundację Matrix.org." @@ -14,20 +14,64 @@ "Użyj innego dostawcy konta, takiego jak własny serwer lub konta służbowego." "Zmień dostawcę konta" "Nie mogliśmy połączyć się z tym serwerem domowym. Sprawdź, czy adres URL serwera został wprowadzony poprawnie. Jeśli adres URL jest poprawny, skontaktuj się z administratorem serwera w celu uzyskania dalszej pomocy." + "Sliding sync nie jest dostępny z powodu problemu w znanym pliku: +%1$s" "Ten serwer obecnie nie obsługuje technologii Sliding Sync." - "Adres URL serwera domowego" + "URL serwera domowego" "Możesz połączyć się tylko z serwerem, który obsługuje technologię Sliding Sync. Administrator serwera domowego będzie musiał ją skonfigurować. %1$s" "Jaki jest adres Twojego serwera?" "Wybierz swój serwer" "To konto zostało dezaktywowane." "Nieprawidłowa nazwa użytkownika i/lub hasło" "To nie jest prawidłowy identyfikator użytkownika. Oczekiwany format: \'@user:homeserver.org\'" + "Ten serwer został skonfigurowany do korzystania z tokenów odświeżania. Nie są one obsługiwane, gdy korzystasz z hasła." "Wybrany serwer domowy nie obsługuje uwierzytelniania hasłem, ani OIDC. Skontaktuj się z jego administratorem lub wybierz inny serwer domowy." "Wprowadź swoje dane" "Matrix to otwarta sieć do bezpiecznej i zdecentralizowanej komunikacji." "Witaj ponownie!" "Zaloguj się do %1$s" + "Nawiązanie bezpiecznego połączenia" + "Nie udało się nawiązać bezpiecznego połączenia z nowym urządzeniem. Twoje istniejące urządzenia są nadal bezpieczne i nie musisz się o nie martwić." + "Co teraz?" + "Spróbuj zalogować się ponownie za pomocą kodu QR, jeśli byłby to problem z siecią" + "Jeśli napotkasz ten sam problem, użyj innej sieci Wi-FI lub danych mobilnych" + "Jeśli to nie zadziała, zaloguj się ręcznie" + "Połączenie nie jest bezpieczne" + "Zostaniesz poproszony o wprowadzenie dwóch cyfr widocznych na tym urządzeniu." + "Wprowadź numer poniżej na innym urządzeniu" + "Zaloguj się na drugie urządzenie lub użyj tego, które jest już zalogowane, a następnie spróbuj ponownie." + "Drugie urządzenie nie jest zalogowane" + "Logowanie zostało anulowane na drugim urządzeniu." + "Prośba o logowanie została anulowana" + "Logowanie zostało odrzucone na drugim urządzeniu." + "Logowanie odrzucone" + "Logowanie wygasło. Spróbuj ponownie." + "Logowanie nie zostało ukończone na czas" + "Twoje drugie urządzenie nie wspiera logowania się do %s za pomocą kodu QR. + +Spróbuj zalogować się ręcznie lub zeskanuj kod QR na innym urządzeniu." + "Kod QR nie jest wspierany" + "Twój dostawca konta nie obsługuje %1$s." + "%1$s nie jest wspierany" + "Gotowy do skanowania" + "Otwórz %1$s na urządzeniu stacjonarnym" + "Kliknij na swój awatar" + "Wybierz %1$s" + "“Powiąż nowe urządzenie”" + "Zeskanuj kod QR za pomocą tego urządzenia" + "Otwórz %1$s na innym urządzeniu, aby uzyskać kod QR" + "Użyj kodu QR widocznego na drugim urządzeniu." "Spróbuj ponownie" + "Błędny kod QR" + "Przejdź do ustawień aparatu" + "Musisz przyznać uprawnienia %1$s do korzystania z kamery, aby kontynuować." + "Zezwól na dostęp do kamery, aby zeskanować kod QR" + "Skanuj kod QR" + "Zacznij od nowa" + "Wystąpił nieoczekiwany błąd. Spróbuj ponownie." + "Oczekiwanie na drugie urządzenie" + "Twój dostawca konta może poprosić o podany kod, aby zweryfikować logowanie." + "Twój kod weryfikacyjny" "Zmień dostawcę konta" "Serwer prywatny dla pracowników Element." "Matrix to otwarta sieć do bezpiecznej i zdecentralizowanej komunikacji." diff --git a/features/login/impl/src/main/res/values-uz/translations.xml b/features/login/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..67dc5129d7 --- /dev/null +++ b/features/login/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,42 @@ + + + "Hisob provayderini o\'zgartiring" + "Uy server manzili" + "Qidiruv so\'zini yoki domen manzilini kiriting." + "Kompaniya, jamoa yoki shaxsiy serverni qidiring." + "Hisob provayderini toping" + "Bu sizning suhbatlaringiz yashaydigan joy - xuddi siz elektron pochta xabarlaringizni saqlash uchun elektron pochta provayderidan foydalanganingiz kabi." + "Siz %sga kirmoqchisiz" + "Bu sizning suhbatlaringiz yashaydigan joy - xuddi siz elektron pochta xabarlaringizni saqlash uchun elektron pochta provayderidan foydalanganingiz kabi." + "Siz %sda hisob yaratmoqchisiz" + "Matrix.org - bu Matrix.org Jamg\'armasi tomonidan boshqariladigan xavfsiz, markazlashtirilmagan aloqa uchun ommaviy Matrix tarmog\'idagi katta, bepul server." + "Boshqa" + "Shaxsiy serveringiz yoki ishchi hisob qaydnomangiz kabi boshqa hisob provayderidan foydalaning." + "Hisob provayderini o\'zgartiring" + "Bu uy serveriga kira olmadik. Iltimos, uy serverining URL manzilini to\'ri kiritganingizni tekshiring. Agar URL toʻgʻri boʻlsa, qoʻshimcha yordam olish uchun uy serveri administratoriga murojaat qiling." + "Hozirda bu server siljish sinxronlashni qo‘llab-quvvatlamaydi." + "Uy serverining URL manzili" + "Siz faqat siljish sinxronlashni qo\'llab-quvvatlaydigan mavjud serverga ulanishingiz mumkin. Uy serveringiz administratori uni sozlashi kerak.%1$s" + "Serveringizning manzili nima?" + "Serveringizni tanlang" + "Bu hisob o‘chirilgan." + "Notog\'ri foydalanuvchi nomi va/yoki parol" + "Bu haqiqiy foydalanuvchi identifikatori emas. Kutilayotgan format: \'@user:homeserver.org\'" + "Tanlangan uy serveri parol yoki OIDC loginni qo\'lab-quvvatlamaydi. Iltimos, administratoringizga murojaat qiling yoki boshqa uy serverini tanlang." + "Tafsilotlaringizni kiriting" + "Matrix xavfsiz, markazlashmagan aloqa uchun ochiq tarmoqdir." + "Qaytib kelganingizdan xursandmiz!" + "Kirish%1$s" + "Hisob provayderini o\'zgartiring" + "Element xodimlari uchun shaxsiy server." + "Matrix xavfsiz, markazlashmagan aloqa uchun ochiq tarmoqdir." + "Bu sizning suhbatlaringiz yashaydigan joy - xuddi siz elektron pochta xabarlaringizni saqlash uchun elektron pochta provayderidan foydalanganingiz kabi." + "Siz tizimga kirmoqchisiz%1$s" + "Hisob yaratmoqchisiz%1$s" + "Hozirgi paytda %2$sga %1$sda talab yuqori. Bir necha kundan keyin ilovaga qayting va qaytadan urining. + +Sabr-toqatingiz uchun rahmat!" + "%1$sga Xush kelibsiz!" + "Siz deyarli keldingiz." + "Siz kirdingiz." + diff --git a/features/logout/impl/src/main/res/values-pt-rBR/translations.xml b/features/logout/impl/src/main/res/values-pt-rBR/translations.xml index 65ccf4ca6f..7d77b477ad 100644 --- a/features/logout/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/logout/impl/src/main/res/values-pt-rBR/translations.xml @@ -4,5 +4,9 @@ "Sair" "Sair" "Saindo…" + "Você desativou o backup" + "O backup das suas chaves ainda está em andamento" "Sair" + "A recuperação não está configurada" + "Você salvou sua chave de recuperação?" diff --git a/features/logout/impl/src/main/res/values-uz/translations.xml b/features/logout/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..24da45d63b --- /dev/null +++ b/features/logout/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,8 @@ + + + "Haqiqatan ham tizimdan chiqmoqchimisiz?" + "Tizimdan chiqish" + "Tizimdan chiqish" + "Chiqish…" + "Tizimdan chiqish" + diff --git a/features/messages/impl/src/main/res/values-pl/translations.xml b/features/messages/impl/src/main/res/values-pl/translations.xml index ebb2b54369..add70eb71d 100644 --- a/features/messages/impl/src/main/res/values-pl/translations.xml +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -39,12 +39,18 @@ "Nowe" "%1$d zmiana pokoju" - "%1$d zmian pokoju" - "%1$d zmiany pokoju" + "%1$d zmiany pokoju" + "%1$d zmian pokoju" + + + "%1$s, %2$s i %3$d inny" + "%1$s, %2$s i %3$d innych" + "%1$s, %2$s i %3$d innych" "%1$s piszę" "%1$s piszą" - "%1$s piszą" + "%1$s pisze" + "%1$s i %2$s" diff --git a/features/messages/impl/src/main/res/values-pt-rBR/translations.xml b/features/messages/impl/src/main/res/values-pt-rBR/translations.xml index 6d324fd695..1c668ae3f6 100644 --- a/features/messages/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/messages/impl/src/main/res/values-pt-rBR/translations.xml @@ -23,6 +23,7 @@ "O histórico de mensagens não está disponível no momento." "Gostaria de convidá-los de volta?" "Você está sozinho neste chat" + "Notificar a sala inteira" "Todos" "Enviar novamente" "Sua mensagem não foi enviada" @@ -36,7 +37,16 @@ "Mostrar mais" "Novo" - "%1$d mudança de sala" - "%1$d mudanças de salas" + "%1$d alteração na sala" + "%1$d alterações na sala" + + "%1$s, %2$s e %3$d outro" + "%1$s, %2$s e %3$d outros" + + + "%1$s está digitando" + "%1$s estão digitando" + + "%1$s e %2$s" diff --git a/features/messages/impl/src/main/res/values-uz/translations.xml b/features/messages/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..78681df692 --- /dev/null +++ b/features/messages/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,42 @@ + + + "Faoliyatlar" + "Bayroqlar" + "Oziq-ovqat va ichimliklar" + "Hayvonlar va tabiat" + "Ob\'ektlar" + "Smayllar va odamlar" + "Sayohat va Joylar" + "Belgilar" + "Foydalanuvchini bloklash" + "Ushbu foydalanuvchidan barcha joriy va kelajakdagi xabarlarni yashirishni xohlayotganingizni tekshiring" + "Bu xabar uy serveringiz administratoriga xabar qilinadi. Ular hech qanday shifrlangan xabarlarni o\'qiy olmaydi." + "Ushbu kontent haqida xabar berish sababi" + "Kamera" + "Rasmga olmoq" + "Video yozib olish" + "Biriktirma" + "Fotosurat va video kutubxonasi" + "Joylashuv" + "So\'ro\'vnoma" + "Matnni formatlash" + "Xabarlar tarixi hozirda mavjud emas." + "Ularni yana taklif qilmoqchimisiz?" + "Siz bu chatda yolg\'izsiz" + "Har kim" + "Yana yuboring" + "Xabaringiz yuborilmadi" + "Emoji qo\'shmoq" + "Bu %1$sni boshlanishi" + "Bu suhbatning boshlanishi." + "Kamroq ko\'rsatish" + "Xabar nusxalandi" + "Sizda bu xonaga post yozishga ruxsat yo‘q" + "Kamroq ko\'rsatish" + "Ko\'proq ko\'rsatish" + "Yangi" + + "%1$dxonani almashtirish" + "%1$dxona o\'zgarishi" + + diff --git a/features/onboarding/impl/src/main/res/values-pt-rBR/translations.xml b/features/onboarding/impl/src/main/res/values-pt-rBR/translations.xml index 04a26fe212..965c66c78c 100644 --- a/features/onboarding/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/onboarding/impl/src/main/res/values-pt-rBR/translations.xml @@ -5,4 +5,5 @@ "Criar conta" "Bem-vindo ao mais rápido %1$s de todos os tempos. Turbinado para velocidade e simplicidade." "Bem-vindo ao %1$s. Turbinado, para velocidade e simplicidade" + "Esteja no seu elemento" diff --git a/features/onboarding/impl/src/main/res/values-uz/translations.xml b/features/onboarding/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..b69af4adb7 --- /dev/null +++ b/features/onboarding/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,9 @@ + + + "Qo\'lda tizimga kiring" + "QR kod bilan tizimga kiring" + "Hisob yaratish" + "Eng tezkor %1$sga xush kelibsiz. Tezlik va oddylik uchun super zaryadlangan." + "%1$sga Xush kelibsiz. Tezlik va oddylik uchun o\'ta zaryadlangan." + "Elementingizda bo\'ling" + diff --git a/features/poll/impl/src/main/res/values-pt-rBR/translations.xml b/features/poll/impl/src/main/res/values-pt-rBR/translations.xml index 058dab7d42..90720720cd 100644 --- a/features/poll/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/poll/impl/src/main/res/values-pt-rBR/translations.xml @@ -7,6 +7,12 @@ "Pergunta ou tópico" "Sobre o que é a enquete?" "Criar enquete" + "Tem certeza de que quer deletar esta enquete?" "Excluir Enquete" "Editar enquete" + "Não foi possível encontrar nenhuma enquete em andamento." + "Não foi possível encontrar nenhuma enquete anterior." + "Em andamento" + "Anteriores" + "Enquetes" diff --git a/features/poll/impl/src/main/res/values-uz/translations.xml b/features/poll/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..ee41d67459 --- /dev/null +++ b/features/poll/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,11 @@ + + + "Variant qo\'shish" + "Natijalarni faqat soʻrov tugagandan keyin koʻrsatish" + "Ovozlarni yashirish" + "Variant%1$d" + "Savol yoki mavzu" + "So\'rovnoma nima haqida?" + "So‘rovnoma yaratish" + "So‘rovnomani tahrirlash" + diff --git a/features/preferences/impl/src/main/res/values-pl/translations.xml b/features/preferences/impl/src/main/res/values-pl/translations.xml index 021d7595f1..6bc66cd63c 100644 --- a/features/preferences/impl/src/main/res/values-pl/translations.xml +++ b/features/preferences/impl/src/main/res/values-pl/translations.xml @@ -3,22 +3,29 @@ "Upewnij się, że nie pominiesz żadnego połączenia. Zmień swoje ustawienia i zezwól na powiadomienia na blokadzie ekranu." "Popraw jakość swoich rozmów" "Wybierz sposób otrzymywania powiadomień" - "Tryb dewelopera" + "Tryb programisty" "Włącz, aby uzyskać dostęp do funkcji dla deweloperów." "Własny bazowy URL dla połączeń Element" "Ustaw własny bazowy URL dla połączeń Element" "Nieprawidłowy adres URL, upewnij się, że zawiera protokół (http/https) i poprawny adres." + "Dostawca powiadomień push" "Wyłącz edytor tekstu bogatego, aby pisać tekst Markdown ręcznie." + "Potwierdzenia odczytania" + "Gdy wyłączona, Twoje potwierdzenia odczytania nie zostaną wysłane. Potwierdzenia od innych wciąż będą odbierane." + "Udostępnij obecność" + "Gdy wyłączona, nie będziesz mógł wysyłać lub odbierać potwierdzeń odczytu ani powiadomień pisania." "Włącz opcję, aby wyświetlić źródło wiadomości na osi czasu." + "Nie blokujesz żadnych użytkowników" "Odblokuj" "Będziesz mógł ponownie zobaczyć wszystkie wiadomości od tego użytkownika." "Odblokuj użytkownika" + "Odblokowuję…" "Wyświetlana nazwa" "Twoja wyświetlana nazwa" "Wystąpił nieznany błąd przez co nie można było zmienić informacji." "Nie można zaktualizować profilu" "Edytuj profil" - "Aktualizowanie profilu…" + "Aktualizuję profil…" "Dodatkowe ustawienia" "Połączenia audio i wideo" "Niezgodność konfiguracji" @@ -46,4 +53,6 @@ Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." "ustawienia systemowe" "Powiadomienia systemowe wyłączone" "Powiadomienia" + "Rozwiązywanie problemów" + "Powiadomienia rozwiązywania problemów" diff --git a/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml b/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml index 2aa9704981..5fbc14c47a 100644 --- a/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml @@ -3,10 +3,18 @@ "Escolha como receber notificações" "Modo de desenvolvedor" "Habilite para ter acesso a recursos e funcionalidades para desenvolvedores." + "URL inválida, por favor verifique se o protocolo (http/https) e o endereço correto estão presentes." "Desative o editor de rich text para digitar Markdown manualmente." + "Confirmações de leitura" + "Se desligado, suas confirmações de leitura não serão enviadas para ninguém. Você ainda receberá confirmações de leitura de outros usuários." + "Compartilhar presença" + "Se desligado, você não poderá enviar ou receber confirmações de leitura ou notificações de digitação." + "Ativar a opção de visualizar o fonte da mensagem na linha do tempo." + "Você não tem usuários bloqueados" "Desbloquear" "Você poderá ver todas as mensagens deles novamente." "Desbloquear usuário" + "Desbloqueando…" "Nome de exibição" "Seu nome de exibição" "Um erro desconhecido foi encontrado e as informações não puderam ser alteradas." @@ -29,6 +37,7 @@ Se você continuar, algumas de suas configurações poderão mudar." "Ativar notificações neste dispositivo" "A configuração não foi corrigida, tente novamente." "Bate-papos em grupo" + "Convites" "Menções" "Todos" "Menções" diff --git a/features/preferences/impl/src/main/res/values-uz/translations.xml b/features/preferences/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..21104e4ab8 --- /dev/null +++ b/features/preferences/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,42 @@ + + + "Bildirishnomalarni qanday qabul qilishni tanlang" + "Dasturchi rejimi" + "Ishlab chiquvchilar uchun xususiyatlar va funksiyalarga kirishni yoqing." + "Maxsus element qo‘ng‘iroqlar bazasi URL manzili" + "Boy matn muharriri o\'chiring Markdown bilan qo\'lda yozish uchun" + "Blokdan chiqarish" + "Ulardan kelgan barcha xabarlarni yana koʻrishingiz mumkin boʻladi." + "Foydalanuvchini blokdan chiqarish" + "Ko\'rsatiladigan ism" + "Ismingizni ko\'rsating" + "Noma\'lum xatolik yuz berdi va ma\'lumotni o\'zgartirib bo\'lmadi." + "Profilni yangilab bo‘lmadi" + "Profilni tahrirlash" + "Profil yangilanmoqda…" + "Qo\'shimcha sozlamalar" + "Audio va video qo\'ng\'iroqlar" + "Konfiguratsiya mos kelmasligi" + "Variantlarni topishni osonlashtirish uchun bildirishnomalar sozlamalarini soddalashtirdik. Ilgari siz tanlagan baʼzi shaxsiy sozlamalar bu yerda koʻrsatilmaydi, lekin ular hali ham faol. + +Davom ettirsangiz, baʼzi sozlamalaringiz oʻzgarishi mumkin." + "To\'g\'ridan-to\'g\'ri suhbatlar" + "Har bir suhbat uchun moslashtirilgan sozlama" + "Bildirishnoma sozlamalarini yangilashda xatolik yuz berdi." + "Barcha xabarlar" + "Faqat eslatmalar va kalit so\'zlar" + "To\'g\'ridan-to\'g\'ri suhbats, menga xabar bering" + "Guruh suhbatlarida menga xabar bering" + "Ushbu qurilmada bildirishnomalarni yoqing" + "Konfiguratsiya tuzatilmadi, qayta urinib ko\'ring." + "Guruh suhbatlari" + "Eslatmalar" + "Hammasi" + "Eslatmalar" + "Menga xabar bering" + "Menga @room orqali xabar bering" + "Bildirishnomalarni olish uchun, iltimos, o\'zingizni %1$singizni o\'zgartiring." + "tizim sozlamalari" + "Tizim bildirishnomalari o\'chirilgan" + "Bildirishnomalar" + diff --git a/features/rageshake/api/src/main/res/values-uz/translations.xml b/features/rageshake/api/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..96032fd65f --- /dev/null +++ b/features/rageshake/api/src/main/res/values-uz/translations.xml @@ -0,0 +1,7 @@ + + + "%1$soxirgi marta ishlatilganda qulab tushdi. Biz bilan nosozlik hisobotini baham ko\'rmoqchimisiz?" + "Siz hafsalasi pir bo\'lib telefonni silkitayotganga o\'xshaysiz. Xatolar haqida hisobot ekranini ochmoqchimisiz?" + "G\'azablanish" + "Aniqlash chegarasi" + diff --git a/features/rageshake/impl/src/main/res/values-pl/translations.xml b/features/rageshake/impl/src/main/res/values-pl/translations.xml index 04bf123498..21e8ad69c6 100644 --- a/features/rageshake/impl/src/main/res/values-pl/translations.xml +++ b/features/rageshake/impl/src/main/res/values-pl/translations.xml @@ -1,12 +1,13 @@ - "Dołącz zrzut ekranu" + "Załącz zrzut ekranu" "Możecie skontaktować się ze mną, jeśli macie jakiekolwiek dodatkowe pytania." "Napisz do mnie" "Edytuj zrzut ekranu" "Opisz problem. Co zrobiłeś? Czego oczekiwałeś? Co się stało zamiast tego. Podaj jak najwięcej szczegółów." "Opisz problem…" "Jeśli to możliwe, napisz zgłoszenje w języku angielskim." + "Opis jest zbyt krótki, podaj więcej szczegółów na temat tego co się stało. Dzięki!" "Wyślij logi awarii" "Zezwól na logi" "Wyślij zrzut ekranu" diff --git a/features/rageshake/impl/src/main/res/values-pt-rBR/translations.xml b/features/rageshake/impl/src/main/res/values-pt-rBR/translations.xml index d046391f6a..885c9a6fe6 100644 --- a/features/rageshake/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/rageshake/impl/src/main/res/values-pt-rBR/translations.xml @@ -12,4 +12,5 @@ "Enviar captura de tela" "Os registros serão incluídos com sua mensagem para garantir que tudo esteja funcionando corretamente. Para enviar sua mensagem sem registros, desative essa configuração." "%1$s fechou inesperadamente na última vez que foi usado. Gostaria de compartilhar um relatório de falhas conosco?" + "Ver registros" diff --git a/features/rageshake/impl/src/main/res/values-uz/translations.xml b/features/rageshake/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..474c775cb0 --- /dev/null +++ b/features/rageshake/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,15 @@ + + + "Ekran tasvirini biriktirish" + "Agar sizda keyingi savollar bo\'lsa, men bilan bog\'lanishingiz mumkin." + "Men bilan bog\'laning" + "Ekran tasvirini tahrirlash" + "Iltimos, muammoni tasvirlab bering. Nima qildingiz? Nima bo\'lishini kutgan edingiz? Aslida nima bo\'ldi. Iltimos, iloji boricha batafsilroq ma\'lumot bering." + "Muammoni tasvirlab bering…" + "Iloji bo\'lsa, tavsifni ingliz tilida yozing." + "Buzilish jurnallarini yuboring" + "Jurnallarga ruxsat bering" + "Ekran tasvirini yuboring " + "Har bir narsa to\'ri ishlayotganiga ishonch hosil qilish uchun xabaringizga jurnallar kiritiladi. Xabarni jurnallarsiz yuborish uchun ushbu sozlamani oʻchiring." + "%1$soxirgi marta ishlatilganda qulab tushdi. Biz bilan nosozlik hisobotini baham ko\'rmoqchimisiz?" + diff --git a/features/roomaliasresolver/impl/src/main/res/values-pl/translations.xml b/features/roomaliasresolver/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..7f830ab944 --- /dev/null +++ b/features/roomaliasresolver/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,4 @@ + + + "Nie udało się uzyskać aliasu pokoju." + diff --git a/features/roomdetails/impl/src/main/res/values-pl/translations.xml b/features/roomdetails/impl/src/main/res/values-pl/translations.xml index 569e167d92..80195a14ea 100644 --- a/features/roomdetails/impl/src/main/res/values-pl/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pl/translations.xml @@ -3,10 +3,41 @@ "Wystąpił błąd podczas aktualizacji ustawienia powiadomień." "Twój serwer domowy nie wspiera tej opcji w pokojach szyfrowanych, możesz nie otrzymać powiadomień z niektórych pokoi." "Ankiety" + "Tylko administratorzy" + "Banowanie osób" + "Usuwanie wiadomości" "Wszyscy" + "Zapraszanie osób" + "Moderacja członków" + "Wiadomości i zawartość" + "Administratorzy i moderatorzy" + "Usuwanie osób" + "Zmień awatar pokoju" + "Szczegóły pokoju" + "Zmień nazwę pokoju" + "Zmień temat pokoju" + "Wysyłanie wiadomości" + "Edytuj administratorów" + "Tej akcji nie będzie można cofnąć. Promujesz użytkownika, który będzie posiadał takie same uprawnienia jak Ty." + "Dodać administratora?" + "Zdegraduj" + "Nie będzie można cofnąć tej zmiany, jeśli się zdegradujesz. Jeśli jesteś ostatnim uprzywilejowanym użytkownikiem w pokoju, nie będziesz w stanie odzyskać uprawnień." + "Zdegradować siebie?" + "%1$s (Oczekujące)" + "(Oczekujący)" + "Administratorzy automatycznie mają uprawnienia moderatora" + "Edytuj moderatorów" + "Administratorzy" + "Moderatorzy" + "Członków" + "Masz niezapisane zmiany." + "Zapisać zmiany?" "Dodaj temat" "Jest już członkiem" "Już zaproszony" + "Szyfrowany" + "Nieszyfrowany" + "Pokój publiczny" "Edytuj pokój" "Wystąpił nieznany błąd i nie można było zmienić informacji." "Nie można zaktualizować pokoju" @@ -21,18 +52,40 @@ "Niestandardowy" "Domyślny" "Powiadomienia" + "Role i uprawnienia" "Nazwa pokoju" "Bezpieczeństwo" "Udostępnij pokój" + "Informacje pokoju" "Temat" "Aktualizuję pokój…" + "Zbanuj" + "Nie będą mogli ponownie dołączyć do tego pokoju, jeśli zostaną zaproszeni." + "Czy na pewno chcesz zbanować tego członka?" + "W tym pokoju nie ma zbanowanych użytkowników." + "Banowanie %1$s" "%1$d osoba" "%1$d osoby" "%1$d osób" + "Usuń i zbanuj członka" + "Usuń z pokoju" + "Usuń i zbanuj członka" + "Tylko usuń członka" + "Usunąć członka i zablokować możliwość dołączenia w przyszłości?" + "Odbanuj" + "Będą mogli ponownie dołączyć do tego pokoju, jeśli zostaną zaproszeni." + "Odbanuj użytkownika" + "Wyświetl profil" + "Zbanowanych" + "Członków" "Oczekiwanie" + "Usuwanie %1$s…" + "Administrator" + "Moderator" "Członkowie pokoju" + "Odbanowanie %1$s" "Zezwalaj na ustawienia niestandardowe" "Włączenie tej opcji nadpisze ustawienie domyślne" "Powiadamiaj mnie o tym czacie przez" @@ -47,4 +100,18 @@ "Wszystkie wiadomości" "Tylko wzmianki i słowa kluczowe" "W tym pokoju, powiadamiaj mnie przez" + "Administratorzy" + "Zmień moją rolę" + "Zdegraduj do członka" + "Zdegraduj do moderatora" + "Moderacja członków" + "Wiadomości i zawartość" + "Moderatorzy" + "Uprawnienia" + "Resetuj uprawnienia" + "Po zresetowaniu uprawnień utracisz bieżące ustawienia." + "Zresetować uprawnienia?" + "Role" + "Szczegóły pokoju" + "Role i uprawnienia" diff --git a/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml b/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml index 4989168201..f7e4d5f9e0 100644 --- a/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml @@ -1,7 +1,29 @@ "Ocorreu um erro ao atualizar a configuração de notificação." + "Enquetes" + "Somente administradores" + "Banir pessoas" + "Remover mensagens" "Todos" + "Convidar pessoas" + "Moderação de membros" + "Mensagens e conteúdo" + "Administradores e moderadores" + "Remover pessoas" + "Alterar avatar da sala" + "Detalhes da sala" + "Alterar nome da sala" + "Alterar tópico da sala" + "Enviar mensagens" + "Editar administradores" + "Adicionar administrador?" + "Editar moderadores" + "Administradores" + "Moderadores" + "Membros" + "Você tem alterações não salvas." + "Salvar alterações?" "Adicionar tópico" "Já é membro" "Já foi convidado" @@ -19,17 +41,35 @@ "Personalizado" "Padrão" "Notificações" + "Cargos e permissões" "Nome da sala" "Segurança" "Compartilhar sala" "Tópico" "Atualizando a sala…" + "Banir" + "Tem certeza de que quer banir este membro?" + "Banindo %1$s" "%1$d pessoa" "%1$d pessoas" + "Remover e banir membro" + "Remover da sala" + "Remover e banir membro" + "Somente remover membro" + "Remover membro e banir de entrar novamente no futuro?" + "Desbanir" + "Desbanir usuário" + "Ver perfil" + "Banidos" + "Membros" "Pendente" + "Removendo %1$s…" + "Administrador" + "Moderador" "Membros da sala" + "Desbanindo %1$s" "Permitir configuração personalizada" "Ativar isso substituirá sua configuração padrão" "Me notifique nesta conversa para" @@ -43,4 +83,15 @@ "Todas as mensagens" "Somente menções e palavras-chave" "Nesta sala, notifique-me para" + "Administradores" + "Alterar meu cargo" + "Moderação de membros" + "Mensagens e conteúdo" + "Moderadores" + "Permissões" + "Redefinir permissões" + "Redefinir permissões?" + "Cargos" + "Detalhes da sala" + "Cargos e permissões" diff --git a/features/roomdetails/impl/src/main/res/values-uz/translations.xml b/features/roomdetails/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..a7d0642bed --- /dev/null +++ b/features/roomdetails/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,45 @@ + + + "Bildirishnoma sozlamalarini yangilashda xatolik yuz berdi." + "Har kim" + "Mavzu qo\'shish" + "Allaqachon a\'zo" + "Allaqachon taklif qilingan" + "Xonani tahrirlash" + "Nomaʼlum xatolik yuz berdi va maʼlumotni oʻzgartirib boʻlmadi." + "Xonani yangilab bo‘lmadi" + "Xabarlar qulflar bilan himoyalangan. Faqat siz va qabul qiluvchilar ularni qulfdan chiqarish uchun noyob kalitlarga ega." + "Xabarni shifrlash yoqilgan" + "Bildirishnoma sozlamalarini yuklashda xatolik yuz berdi." + "Bu xona ovozini o‘chirib bo‘lmadi, qayta urinib ko‘ring." + "Bu xonaning ovozi yoqilmadi, qayta urinib ko‘ring." + "Odamlarni taklif qiling" + "Xonani tark etish " + "Maxsus" + "Standart" + "Bildirishnomalar" + "Xona nomi" + "Xavfsizlik" + "Xonani baham ko\'ring" + "Mavzu" + "Xona yangilanmoqda…" + + "%1$dodam" + "%1$dodamlar" + + "Kutilmoqda" + "Xona a\'zolari" + "Moslashtirilgan sozlamalarga ruxsat bering" + "Buni yoqsangiz, standart sozlamalaringiz bekor qilinadi" + "Bu chatda menga xabar bering" + "Siz buni o\'zgartira olasiz o\'zingizning %1$sda." + "global sozlamalar" + "Standart sozlama" + "Maxsus sozlamani olib tashlang" + "Bildirishnoma sozlamalarini yuklashda xatolik yuz berdi." + "Standart rejimni tiklab bo‘lmadi, qaytadan urinib ko‘ring." + "Rejimni o‘rnatib bo‘lmadi, qayta urinib ko‘ring." + "Barcha xabarlar" + "Faqat eslatmalar va kalit so\'zlar" + "Bu xonada menga xabar bering" + diff --git a/features/roomdirectory/impl/src/main/res/values-pl/translations.xml b/features/roomdirectory/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..80bbffed87 --- /dev/null +++ b/features/roomdirectory/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,5 @@ + + + "Błąd wczytywania" + "Katalog pokoi" + diff --git a/features/roomdirectory/impl/src/main/res/values-pt-rBR/translations.xml b/features/roomdirectory/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..07bbad975f --- /dev/null +++ b/features/roomdirectory/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,4 @@ + + + "Diretório de salas" + diff --git a/features/roomlist/impl/src/main/res/values-pl/translations.xml b/features/roomlist/impl/src/main/res/values-pl/translations.xml index 0ae62297a1..96d91a568f 100644 --- a/features/roomlist/impl/src/main/res/values-pl/translations.xml +++ b/features/roomlist/impl/src/main/res/values-pl/translations.xml @@ -1,10 +1,10 @@ "Twoja kopia zapasowa czatu jest obecnie niezsynchronizowana. Aby zachować dostęp do kopii zapasowej czatu, musisz potwierdzić klucz odzyskiwania." - "Potwierdź klucz odzyskiwania" + "Wprowadź swój klucz przywracania" "Upewnij się, że nie pominiesz żadnego połączenia. Zmień swoje ustawienia i zezwól na powiadomienia na blokadzie ekranu." "Popraw jakość swoich rozmów" - "Czy na pewno chcesz odrzucić zaproszenie do dołączenia do %1$s?" + "Czy na pewno chcesz odrzucić zaproszenie dołączenia do %1$s?" "Odrzuć zaproszenie" "Czy na pewno chcesz odrzucić rozmowę prywatną z %1$s?" "Odrzuć czat" @@ -15,8 +15,26 @@ "Utwórz nową rozmowę lub pokój" "Wyślij komuś wiadomość, aby rozpocząć." "Brak czatów." + "Ulubione" + "Możesz dodać czat do ulubionych w ustawieniach czatu. +Na razie możesz wyczyścić filtry, aby zobaczyć pozostałe czaty" + "Nie masz jeszcze ulubionych czatów" + "Zaproszenia" + "Nie masz żadnych oczekujących zaproszeń." + "Niski priorytet" + "Wyczyść filtry, aby zobaczyć pozostałe czaty" + "Brak czatów dla podanych kryteriów" "Osoby" + "Nie masz jeszcze żadnych PW" + "Pokoje" + "Nie jesteś jeszcze w żadnym pokoju" + "Nieprzeczytane" + "Gratulacje! +Nie masz żadnych nieprzeczytanych wiadomości!" "Wszystkie czaty" + "Oznacz jako przeczytane" + "Oznacz jako nieprzeczytane" + "Przeglądaj wszystkie pokoje" "Wygląda na to, że używasz nowego urządzenia. Zweryfikuj się innym urządzeniem, aby uzyskać dostęp do zaszyfrowanych wiadomości." "Potwierdź, że to Ty" diff --git a/features/roomlist/impl/src/main/res/values-pt-rBR/translations.xml b/features/roomlist/impl/src/main/res/values-pt-rBR/translations.xml index 6765199a70..5f896a6427 100644 --- a/features/roomlist/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/roomlist/impl/src/main/res/values-pt-rBR/translations.xml @@ -12,8 +12,21 @@ "Criar uma nova conversa ou sala" "Comece enviando uma mensagem para alguém." "Ainda não há conversas." + "Favoritos" + "Você não tem nenhuma conversa favorita ainda" + "Baixa prioridade" + "Você não tem conversas para esta seleção" "Pessoas" + "Você não tem nenhum conversa privada ainda" + "Salas" + "Você não está em nenhuma sala ainda" + "Não lidos" + "Parabéns! +Você não tem nenhuma mensagem não lida!" "Conversas" + "Marcar como lido" + "Marcar como não lido" + "Navegar por todas as salas" "Parece que você está usando um novo dispositivo. Verifique com outro dispositivo para acessar suas mensagens criptografadas." "Verifique se é você" diff --git a/features/roomlist/impl/src/main/res/values-uz/translations.xml b/features/roomlist/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..7ca2ae798a --- /dev/null +++ b/features/roomlist/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,18 @@ + + + "Haqiqatan ham qo\'shilish taklifini rad qilmoqchimisiz%1$s ?" + "Taklifni rad etish" + "Haqiqatan ham bu shaxsiy chatni rad qilmoqchimisiz%1$s ?" + "Chatni rad etish" + "Takliflar yo\'q" + "%1$s(%2$s ) sizni taklif qildi" + "Bu bir martalik jarayon, kutganingiz uchun rahmat." + "Hisobingiz sozlanmoqda." + "Yangi suhbat yoki xona yarating" + "Kimgadir xabar yuborishdan boshlang." + "Hozircha chatlar yo‘q." + "Odamlar" + "Suhbatlar" + "Siz yangi qurilmadan foydalanayotganga o‘xshaysiz. Shifrlangan xabarlaringizga kirish uchun boshqa qurilma bilan tasdiqlang." + "Siz ekanligingizni tasdiqlang" + diff --git a/features/securebackup/impl/src/main/res/values-pl/translations.xml b/features/securebackup/impl/src/main/res/values-pl/translations.xml index ca1589c5ac..17a4c1a4db 100644 --- a/features/securebackup/impl/src/main/res/values-pl/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pl/translations.xml @@ -6,11 +6,18 @@ "Backup" "Zmień klucz przywracania" "Wprowadź klucz przywracania" - "Backup czatu nie jest zsynchronizowany." + "Backup czatu jest niezsynchronizowany." "Skonfiguruj przywracanie" "Uzyskaj dostęp do swoich wiadomości szyfrowanych, jeśli utracisz wszystkie swoje urządzenia lub zostaniesz wylogowany z %1$s." + "Otwórz %1$s na urządzeniu stacjonarnym" + "Zaloguj się ponownie na swoje konto" + "Gdy pojawi się prośba o weryfikację urządzenia, wybierz %1$s" + "“Resetuj wszystko”" + "Postępuj zgodnie z instrukcjami, aby utworzyć nowy klucz przywracania" + "Zapisz nowy klucz przywracania w menedżerze haseł lub notatce szyfrowanej" + "Resetuj szyfrowanie swojego konta za pomocą drugiego urządzenia" "Wyłącz" - "Utracisz dostęp do wiadomości szyfrowanych, jeśli zostaniesz wylogowany ze wszystkich urządzeń." + "Jeśli wylogujesz się ze wszystkich urządzeń, stracisz wszystkie wiadomości szyfrowane." "Czy na pewno chcesz wyłączyć backup?" "Wyłączenie backupu spowoduje usunięcie kopii klucza szyfrowania i wyłączenie innych funkcji bezpieczeństwa. W takim przypadku będziesz:" "Posiadał historii wiadomości szyfrowanych na nowych urządzeniach" @@ -21,11 +28,14 @@ "Upewnij się, że klucz przywracania będzie trzymany w bezpiecznym miejscu" "Zmieniono klucz przywracania" "Zmienić klucz przywracania?" + "Utwórz nowy klucz przywracania" "Upewnij się, że nikt nie widzi tego ekranu!" "Spróbuj ponownie, aby potwierdzić dostęp do backupu czatu." "Nieprawidłowy klucz przywracania" "To też zadziała, jeśli posiadasz klucz lub frazę bezpieczeństwa." + "Klucz przywracania lub hasło" "Wprowadź…" + "Zgubiłeś swój kod przywracania?" "Potwierdzono klucz przywracania" "Wprowadź klucz przywracania" "Skopiowano klucz przywracania" diff --git a/features/securebackup/impl/src/main/res/values-pt-rBR/translations.xml b/features/securebackup/impl/src/main/res/values-pt-rBR/translations.xml index 786de3f4da..9c9ea39c24 100644 --- a/features/securebackup/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pt-rBR/translations.xml @@ -4,7 +4,7 @@ "Ativar o backup" "O backup garante que você não perca seu histórico de mensagens. %1$s." "Backup" - "Mudar chave de recuperação" + "Alterar chave de recuperação" "Insira a chave de recuperação" "Seu backup das conversas está atualmente fora de sincronia." "Configurar a recuperação" @@ -22,10 +22,13 @@ "Chave de recuperação alterada" "Alterar chave de recuperação?" "Certifique-se de que ninguém possa ver essa tela!" + "Chave de recuperação incorreta" "Se você tiver uma chave de segurança ou frase de segurança, isso também funcionará." "Inserir…" "Chave de recuperação confirmada" "Insira sua chave de recuperação" + "Chave de recuperação copiada" + "Gerando…" "Salvar chave de recuperação" "Anote sua chave de recuperação em algum lugar seguro ou salve-a em um gerenciador de senhas." "Toque para copiar a chave de recuperação" diff --git a/features/securebackup/impl/src/main/res/values-uz/translations.xml b/features/securebackup/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..b5bea8f4b8 --- /dev/null +++ b/features/securebackup/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,40 @@ + + + "Zaxiralashni o\'chirib qo\'ying" + "Zaxiralashni yoqing" + "Zaxiralash xabarlar tarixini yo\'qotmaslikni ta\'minlaydi.%1$s." + "Zaxira" + "Qayta tiklash kalitini o\'zgartiring" + "Qayta tiklash kalitini kiriting" + "Sizning chat zaxirangiz hozirda sinxronlashtirilmagan." + "Qayta tiklashni sozlang" + "Agar barcha qurilmalaringizni yo‘qotib qo‘ysangiz yoki tizimdan chiqqan bo‘lsangiz, shifrlangan xabarlaringizga ruxsat oling%1$s hamma joyda." + "O\'chirish" + "Agar barcha qurilmalardan chiqqan boʻlsangiz, shifrlangan xabarlaringizni yoʻqotasiz." + "Haqiqatan ham zaxiralashni o‘chirib qo‘ymoqchimisiz?" + "Zaxiralashni o‘chirib qo‘ysangiz, joriy shifrlash kaliti zaxira nusxasi o‘chiriladi va boshqa xavfsizlik funksiyalari o‘chiriladi. Bunday holda siz:" + "Yangi qurilmalarda shifrlangan xabarlar tarixi mavjud emas" + "Agar tizimdan chiqqan boʻlsangiz, shifrlangan xabarlaringizga kirish huquqini yoʻqotasiz%1$s hamma joyda" + "Haqiqatan ham zaxiralashni o‘chirib qo‘ymoqchimisiz?" + "Mavjud kalitingizni yo\'qotgan bo\'lsangiz, yangi tiklash kalitini oling. Qayta tiklash kalitini almashtirganingizdan so\'ng, eski kalitingiz ishlamaydi." + "Yangi tiklash kalitini yarating" + "Qayta tiklash kalitingizni xavfsiz joyda saqlashingiz mumkinligiga ishonch hosil qiling" + "Qayta tiklash kaliti oʻzgartirildi" + "Qayta tiklash kaliti almashtirilsinmi?" + "Hech kim bu ekranni kora olmasligiga ishonch hosil qiling!" + "Agar sizda xavfsizlik kaliti yoki xavfsizlik iborasi bolsa, bu ham ishlaydi." + "Kirish…" + "Qayta tiklash kaliti tasdiqlandi" + "Qayta tiklash kalitingizni kiriting" + "Qayta tiklash kalitini saqlang" + "Qayta tiklash kalitingizni xavfsiz joyga yozing yoki parol menejerida saqlang." + "Qayta tiklash kalitidan nusxa olish uchun bosing" + "Zaxira kalitingizni saqlang" + "Ushbu qadamdan so‘ng siz yangi tiklash kalitingizga kira olmaysiz." + "Zaxira kalitingizni saqladingizmi?" + "Suhbatingiz zaxira nusxasi tiklash kaliti bilan himoyalangan. Agar sozlashdan keyin sizga yangi tiklash kaliti kerak boʻlsa, “Qayta tiklash kalitini oʻzgartirish”ni tanlash orqali qayta yaratishingiz mumkin." + "Qayta tiklash kalitini yarating" + "Qayta tiklash kalitingizni xavfsiz joyda saqlashingiz mumkinligiga ishonch hosil qiling" + "Qayta tiklash muvaffaqiyatli sozlandi" + "Qayta tiklashni sozlang" + diff --git a/features/signedout/impl/src/main/res/values-uz/translations.xml b/features/signedout/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..bb386ee54f --- /dev/null +++ b/features/signedout/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,8 @@ + + + "Siz boshqa seansda parolingizni o\'zgartirdingiz" + "Siz seansni boshqa seansdan o\'chirib tashladingiz" + "Serveringiz administratori ruxsatingizni bekor qildi" + "Siz quyida sanab o‘tilgan sabablardan biri tufayli tizimdan chiqqan bo‘lishingiz mumkin. Foydalanishni davom ettirish uchun qayta kiring%s ." + "Hisobingizdan chiqdingiz" + diff --git a/features/userprofile/shared/src/main/res/values-uz/translations.xml b/features/userprofile/shared/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..5c7e50eaec --- /dev/null +++ b/features/userprofile/shared/src/main/res/values-uz/translations.xml @@ -0,0 +1,10 @@ + + + "Bloklash" + "Bloklangan foydalanuvchilar sizga xabar yubora olmaydi va ularning barcha xabarlari yashiriladi. Ularni istalgan vaqtda blokdan chiqarishingiz mumkin." + "Foydalanuvchini bloklash" + "Blokdan chiqarish" + "Ulardan kelgan barcha xabarlarni yana koʻrishingiz mumkin boʻladi." + "Foydalanuvchini blokdan chiqarish" + "Suhbatni boshlashda xatolik yuz berdi" + diff --git a/features/verifysession/impl/src/main/res/values-pl/translations.xml b/features/verifysession/impl/src/main/res/values-pl/translations.xml index 6f39abf905..765d141669 100644 --- a/features/verifysession/impl/src/main/res/values-pl/translations.xml +++ b/features/verifysession/impl/src/main/res/values-pl/translations.xml @@ -1,11 +1,19 @@ + "Utwórz nowy klucz przywracania" + "Zweryfikuj to urządzenie, aby skonfigurować bezpieczne przesyłanie wiadomości." + "Potwierdź, że to Ty" + "Teraz możesz bezpiecznie czytać i wysyłać wiadomości, każdy z kim czatujesz również może ufać temu urządzeniu." + "Urządzenie zweryfikowane" + "Użyj innego urządzenia" + "Oczekiwanie na inne urządzenie…" "Coś tu nie gra. Albo upłynął limit czasu, albo żądanie zostało odrzucone." - "Upewnij się, że poniższe emotikony pasują do tych wyświetlanych na innej sesji." + "Upewnij się, że emoji poniżej pasują do tych pokazanych na innej sesji." "Porównaj emotki" "Upewnij się, że liczby poniżej pasują do tych wyświetlanych na innej sesji." "Porównaj liczby" "Twoja nowa sesja jest teraz zweryfikowana. Ma ona dostęp do Twoich zaszyfrowanych wiadomości, a inni użytkownicy będą widzieć ją jako zaufaną." + "Wprowadź klucz przywracania" "Udowodnij, że to ty, aby uzyskać dostęp do historii zaszyfrowanych wiadomości." "Otwórz istniejącą sesję" "Ponów weryfikację" diff --git a/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml b/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml index 9d4658be82..3649a88f05 100644 --- a/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml @@ -1,14 +1,20 @@ + "Dispositivo verificado" + "Usar outro dispositivo" "Algo não parece certo. Ou a solicitação atingiu o tempo limite ou a solicitação foi negada." "Confirme se os emojis abaixo correspondem aos mostrados em sua outra sessão." "Compare os emojis" + "Confirme se os números abaixo correspondem aos mostrados em sua outra sessão." + "Comparar números" "Sua nova sessão está agora verificada. Ela tem acesso às suas mensagens criptografadas e outros usuários a verão como confiável." + "Insira a chave de recuperação" "Prove que é você para acessar seu histórico de mensagens criptografadas." "Abrir uma sessão existente" "Repetir verificação" "Estou pronto" "Esperando para combinar" + "Compare um conjunto único de emojis." "Compare os emojis únicos, garantindo que apareçam na mesma ordem." "Eles não combinam" "Eles combinam" diff --git a/features/verifysession/impl/src/main/res/values-uz/translations.xml b/features/verifysession/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..87b780aa1a --- /dev/null +++ b/features/verifysession/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,17 @@ + + + "Nimadir noto‘g‘ri ko‘rinadi. Yoki so‘rov muddati tugadi yoki so‘rov rad etildi." + "Quyidagi kulgichlar boshqa seansda ko‘rsatilganlarga mos kelishini tasdiqlang." + "Emojilarni solishtiring" + "Yangi seansingiz tasdiqlandi. U sizning shifrlangan xabarlaringizga kirish huquqiga ega va boshqa foydalanuvchilar uni ishonchli deb bilishadi." + "Shifrlangan xabarlar tarixiga kirish uchun shaxsingizni tasdiqlang." + "Mavjud seansni oching" + "Tasdiqlashni qaytadan urining" + "Men tayyorman" + "Mos kelishi kutilmoqda" + "Noyob emojilarni solishtiring, ular bir xil tartibda paydo bo\'lishiga ishonch hosil qiling." + "Ular mos kelmaydi" + "Ular mos keladi" + "Davom etish uchun boshqa seansda tekshirish jarayonini boshlash soʻrovini qabul qiling." + "Soʻrovni qabul qilish kutilmoqda" + diff --git a/libraries/androidutils/src/main/res/values-uz/translations.xml b/libraries/androidutils/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..a41abbde52 --- /dev/null +++ b/libraries/androidutils/src/main/res/values-uz/translations.xml @@ -0,0 +1,4 @@ + + + "Bu amalni bajarish uchun mos ilova topilmadi." + diff --git a/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml b/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml index 0c3bddc3c1..2efaca2b08 100644 --- a/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml @@ -3,12 +3,16 @@ "(zdjęcie profilowe też zostało zmienione)" "%1$s zmienił swoje zdjęcie profilowe" "Zmieniłeś swoje zdjęcie profilowe" + "%1$s został zdegradowany do członka" + "%1$s został zdegradowany do moderatora" "%1$s zmienił swoją wyświetlaną nazwę z %2$s na %3$s" "Zmieniłeś swoją wyświetlaną nazwę z %1$s na %2$s" "%1$s usunął swoją wyświetlaną nazwę (byo to %2$s)" "Usunąłeś swoją wyświetlaną nazwę (było to %1$s)" "%1$s ustawił swoją wyświetlaną nazwę na %2$s" "Ustawiłeś swoją wyświetlaną nazwę na %1$s" + "%1$s został awansowany na administratora" + "%1$s został awansowany na moderatora" "%1$s zmienił zdjęcie profilowe pokoju" "Zmieniłeś zdjęcie profilowe pokoju" "%1$s usunął zdjęcie profilowe pokoju" @@ -42,7 +46,7 @@ "%1$s nie wprowadził żadnych zmian" "Nie wprowadzono żadnych zmian" "%1$s odrzucił zaproszenie" - "Odrzuciłeś(aś) zaproszenie" + "Odrzuciłeś zaproszenie" "%1$s usunął %2$s" "Usunąłeś %1$s" "%1$s wysłał zaproszenie do %2$s, aby dołączył do pokoju" diff --git a/libraries/eventformatter/impl/src/main/res/values-pt-rBR/translations.xml b/libraries/eventformatter/impl/src/main/res/values-pt-rBR/translations.xml index 8cb375f1b7..5148cc7638 100644 --- a/libraries/eventformatter/impl/src/main/res/values-pt-rBR/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-pt-rBR/translations.xml @@ -3,12 +3,16 @@ "(o avatar também foi alterado)" "%1$s mudou seu avatar" "Você mudou seu avatar" + "%1$s foi rebaixado a membro" + "%1$s foi rebaixado a moderador" "%1$s mudou seu nome de exibição de %2$s para %3$s" "Você alterou seu nome de exibição de %1$s para %2$s" "%1$s removeu seu nome de exibição (era %2$s)" "Você removeu seu nome de exibição (era %1$s)" "%1$s definiu seu nome de exibição como %2$s" "Você definiu seu nome de exibição como %1$s" + "%1$s foi promovido a administrador" + "%1$s foi promovido a moderador" "%1$s mudou o avatar da sala" "Você mudou o avatar da sala" "%1$s removeu o avatar da sala" @@ -39,6 +43,8 @@ "Você mudou o nome da sala para: %1$s" "%1$s removeu o nome da sala" "Você removeu o nome da sala" + "%1$s não fez alterações" + "Você não fez nenhuma alteração" "%1$s rejeitou o convite" "Você rejeitou o convite" "%1$s removido %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-uz/translations.xml b/libraries/eventformatter/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..5afcc9b061 --- /dev/null +++ b/libraries/eventformatter/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,57 @@ + + + "(avatar ham o\'zgartirildi)" + "%1$s avatarini o\'zgartirdi" + "Siz avataringizni o\'zgartirdingiz" + "%1$s ko\'rsatiladigan nomini %2$sdan %3$sga o\'zgartirdi" + "Siz ko\'rsatiladigan nomingizni %1$s dan %2$s ga o\'zgartirdingiz" + "%1$s ko\'rinadigan nomini o\'chirib tashladi (avval %2$s bo\'lgan edi)" + "Siz ko\'rinadigan nomingizni o\'chirib tashladingiz (avval %1$s bo\'lgan edi)" + "%1$s ularning ko\'rsatiladigan nomini o\'rnating %2$s" + "Siz ko\'rsatiladigan nomingizni o\'rnating %1$s" + "%1$s xonani avatarini o\'zgartirdi" + "Siz xonani avatarini o\'zgartirdingiz" + "%1$s xonani avatarini o\'chirib tashladi" + "Siz xonani avatarini o\'chirib tashladingiz" + "%1$staqiqlangan%2$s" + "Siz taqiqlangansiz%1$s" + "%1$sxonani yaratdi" + "Siz xonani yaratdingiz" + "%1$staklif qilingan%2$s" + "%1$staklifni qabul qildi" + "Siz taklifni qabul qildingiz" + "Siz taklif qildingiz%1$s" + "%1$ssizni taklif qildi" + "%1$sxonaga qo\'shildi" + "Siz xonaga qo\'shildingiz" + "%1$s qo\'shilishni so\'radi" + "%1$s %2$sga qo\'shilishga ruxsat berdi" + "Siz %1$sga qo\'shilishaga ruxsat berdingiz" + "Siz qoʻshilishni soʻragansiz" + "%1$s %2$sning qo\'shilish haqidagi iltimosini rad etdi" + "Siz %1$sning qo\'shiliz iltimosini rad etdingiz" + "%1$s sizni qo\'shilish iltimosingizni rad etdi" + "%1$ endi qo\'shilishdan manfaatdor emas" + "Siz qoʻshilish soʻrovingizni bekor qildingiz" + "%1$sxonani tark etdi" + "Siz xonani tark etdingiz" + "%1$s xonani nomini %2$s o\'zgartirdi" + "Siz xonani nomini %1$s ga o\'zgartirdingiz" + "%1$s xonani nomini o\'chirib tashladi" + "Siz xonani nomini o\'chirib tashladingiz" + "%1$staklifni rad etdi" + "Siz taklifni rad etdingiz" + "%1$o\'chirildi%2$s" + "siz o\'chirildingiz%1$s" + "%1$s taklifnoma yubordi %2$sga xonaga qo\'shilish uchun" + "Siz taklifnoma yubordingiz %1$sga xonaga qo\'shilishi uchun" + "%1$s taklifni %2$sga xonaga qo\'shilish uchun bekor qildi" + "Siz xonaga qo\'shilish taklifini $1$s ga bekor qildingiz" + "%1$s mavzuni %2$s o\'zgartirdi" + "Siz mavzuni %1$s ga o\'zgartirdingiz" + "%1$s xonani mavzusini o\'chirib tashladi" + "Siz xonani mavzusini o\'chirib tashladingiz" + "%1$staqiqlanmagan%2$s" + "Siz %1$s taqiqini bekor qildingiz" + "%1$s aʼzoligiga nomaʼlum oʻzgarishlar kiritdi" + diff --git a/libraries/matrixui/src/main/res/values-uz/translations.xml b/libraries/matrixui/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..069f0b8372 --- /dev/null +++ b/libraries/matrixui/src/main/res/values-uz/translations.xml @@ -0,0 +1,4 @@ + + + "%1$s(%2$s ) sizni taklif qildi" + diff --git a/libraries/permissions/api/src/main/res/values-uz/translations.xml b/libraries/permissions/api/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..3106daedb7 --- /dev/null +++ b/libraries/permissions/api/src/main/res/values-uz/translations.xml @@ -0,0 +1,7 @@ + + + "Ilovaga kameradan foydalanishiga ruxsat berish uchun tizim sozlamalarida ruxsat bering." + "Iltimos, tizim sozlamalarida ruxsat bering." + "Ilovaga mikrofondan foydalanishiga ruxsat berish uchun tizim sozlamalarida ruxsat bering." + "Ilova bildirishnomalarni ko\'rsatishi uchun tizim sozlamalarida ruxsat bering." + diff --git a/libraries/permissions/impl/src/main/res/values-pl/translations.xml b/libraries/permissions/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..c3f5197d95 --- /dev/null +++ b/libraries/permissions/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,5 @@ + + + "Sprawdź, czy aplikacja może wyświetlać powiadomienia." + "Sprawdź uprawnienia" + diff --git a/libraries/push/impl/src/main/res/values-pl/translations.xml b/libraries/push/impl/src/main/res/values-pl/translations.xml index 56d65b15cb..d5f77da93e 100644 --- a/libraries/push/impl/src/main/res/values-pl/translations.xml +++ b/libraries/push/impl/src/main/res/values-pl/translations.xml @@ -34,6 +34,7 @@ "%d nowych wiadomości" "Zareagował z %1$s" + "Oznacz jako przeczytane" "Szybka odpowiedź" "Zaprosił Cię do dołączenia do pokoju" "Ja" @@ -56,4 +57,29 @@ "Synchronizacja w tle" "Usługi Google" "Nie znaleziono usług Google Play. Powiadomienia mogą nie działać prawidłowo." + "Uzyskaj nazwę bieżącego dostawcy." + "Nie wybrano dostawców push." + "Bieżący dostawca push: %1$s." + "Bieżący dostawca push" + "Upewnij się, że aplikacja ma co najmniej jednego dostawcę push." + "Nie znaleziono dostawców push." + + "Znaleziono %1$d dostawcę push: %2$s" + "Znaleziono %1$d dostawców push: %2$s" + "Znaleziono %1$d dostawców push: %2$s" + + "Wykryj dostawców powiadomień push" + "Sprawdź, czy aplikacja może wyświetlać powiadomienie." + "Powiadomienie nie zostało kliknięte." + "Nie można wyświetlić powiadomienia." + "Powiadomienie zostało kliknięte!" + "Wyświetl powiadomienie" + "Kliknij powiadomienie, aby kontynuować test." + "Upewnij się, że aplikacja otrzymuje powiadomienie push." + "Błąd: pusher odrzucił żądanie." + "Błąd: %1$s." + "Błąd, nie można przetestować push." + "Błąd, upłynął limit czasu powiadomienia push." + "Pętla powrotna push zajęła %1$d ms." + "Przetestuj pętlę Push back" diff --git a/libraries/push/impl/src/main/res/values-pt-rBR/translations.xml b/libraries/push/impl/src/main/res/values-pt-rBR/translations.xml index dbdc30a031..3d647e1acf 100644 --- a/libraries/push/impl/src/main/res/values-pt-rBR/translations.xml +++ b/libraries/push/impl/src/main/res/values-pt-rBR/translations.xml @@ -21,12 +21,14 @@ "%d convites" "Convidou você para conversar" + "Mencionou você: %1$s" "Novas mensagens" "%d nova mensagem" "%d novas mensagens" "Reagiu com %1$s" + "Marcar como lido" "Resposta rápida" "Convidou você para entrar na sala" "Eu" diff --git a/libraries/push/impl/src/main/res/values-uz/translations.xml b/libraries/push/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..77e503e5c9 --- /dev/null +++ b/libraries/push/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,50 @@ + + + "Qo\'ng\'iroq" + "Voqealarni tinglash" + "Shovqinli bildirishnomalar" + "Ovozsiz bildirishnomalar" + + "%1$s:%2$d xabar" + "%1$s:%2$d xabarlar" + + + "%dbildirishnoma" + "%dbildirishnomalar" + + "Bildirishnoma" + "** Yuborilmadi - iltimos, xonani oching" + "Qo\'shilish" + "Rad etish" + + "%dtaklifnoma" + "%dtaklifnomalar" + + "Sizni suhbatga taklif qildi" + "Yangi xabarlar" + + "%dyangi xabar" + "%dyangi xabarlar" + + "%1$sbilan munosabat bildiring" + "Tez javob" + "Sizni xonaga kirishga taklif qildi" + "Men" + "Siz bildirishnomani ko\'ryapsiz! Meni bosing!" + "%1$s:%2$s" + "%1$s:%2$s%3$s" + + "%do\'qilmagan xabarnoma" + "%do\'qilmagan xabarlar" + + "%1$sva%2$s" + "%1$sichida%2$s" + "%1$sichida%2$s va%3$s" + + "%dxona" + "%dxonalar" + + "Orqa Fon sinxronizatsiyasi" + "Google xizmatlari" + "Yaroqli Google Play xizmatlari topilmadi. Bildirishnomalar to\'g\'ri ishlamasligi mumkin." + diff --git a/libraries/pushproviders/firebase/src/main/res/values-pl/translations.xml b/libraries/pushproviders/firebase/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..7a3e164465 --- /dev/null +++ b/libraries/pushproviders/firebase/src/main/res/values-pl/translations.xml @@ -0,0 +1,11 @@ + + + "Upewnij się, że Firebase jest dostępny." + "Baza Firebase jest niedostępna." + "Baza Firebase jest dostępna." + "Sprawdź Firebase" + "Upewnij się, że token Firebase jest dostępny." + "Token Firebase nie jest znany." + "Token Firebase: %1$s." + "Sprawdź token Firebase" + diff --git a/libraries/pushproviders/unifiedpush/src/main/res/values-pl/translations.xml b/libraries/pushproviders/unifiedpush/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..d12f81977f --- /dev/null +++ b/libraries/pushproviders/unifiedpush/src/main/res/values-pl/translations.xml @@ -0,0 +1,11 @@ + + + "Upewnij się, że dystrybutorzy UnifiedPush są dostępni." + "Nie znaleziono dystrybutorów push." + + "Znaleziono %1$d dystrybutora: %2$s." + "Znaleziono %1$d dystrybutorów: %2$s." + "Znaleziono %1$d dystrybutorów: %2$s." + + "Sprawdź UnifiedPush" + diff --git a/libraries/textcomposer/impl/src/main/res/values-pl/translations.xml b/libraries/textcomposer/impl/src/main/res/values-pl/translations.xml index 484b3b622c..c48403de54 100644 --- a/libraries/textcomposer/impl/src/main/res/values-pl/translations.xml +++ b/libraries/textcomposer/impl/src/main/res/values-pl/translations.xml @@ -7,14 +7,14 @@ "Wiadomość…" "Utwórz link" "Edytuj link" - "Zastosuj pogrubiony format" - "Zastosuj format kursywy" - "Zastosuj format przekreślenia" - "Zastosuj format podkreślenia" - "Przełącz tryb pełnoekranowy" + "Zastosuj pogrubienie" + "Zastosuj kursywę" + "Zastosuj przekreślenie" + "Zastosuj podkreślenie" + "Przełącz pełny ekran" "Wcięcie" - "Zastosuj format kodu wbudowanego" - "Wstaw łącze" + "Zastosuj formatowanie kodu w wierszu" + "Wstaw link" "Przełącz listę numerowaną" "Otwórz opcje tworzenia" "Przełącz cytat" diff --git a/libraries/textcomposer/impl/src/main/res/values-pt-rBR/translations.xml b/libraries/textcomposer/impl/src/main/res/values-pt-rBR/translations.xml index 332f97e155..592050a625 100644 --- a/libraries/textcomposer/impl/src/main/res/values-pt-rBR/translations.xml +++ b/libraries/textcomposer/impl/src/main/res/values-pt-rBR/translations.xml @@ -12,12 +12,14 @@ "Aplicar formato tachado" "Aplicar sublinhado" "Alternar o modo de tela cheia" + "Identar" "Aplicar formato de código embutido" "Definir link" "Alternar lista numerada" "Abrir opções de composição" "Alternar citação" "Remover link" + "Desidentar" "Link" "Segure para gravar" diff --git a/libraries/textcomposer/impl/src/main/res/values-uz/translations.xml b/libraries/textcomposer/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..bc6cd60cb1 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,25 @@ + + + "Biriktirma qo\'shing" + "Belgilar roʻyxatini almashtirish" + "Formatlash parametrlarini yoping" + "Kod blokini almashtirish" + "Xabar…" + "Havola yarating" + "Havolani tahrirlash" + "Qalin formatni qo\'llang" + "Kursiv formatini qo\'llang" + "Chizilgan formatni qo\'llash" + "Pastki chiziq formatini qo\'llang" + "Toʻliq ekran rejimiga oʻtish" + "Paragraf" + "Koq formatini mos ravishda qo\'shing" + "Havolani o\'rnatish" + "Raqamlangan roʻyxatni almashtirish" + "Yozish parametrlarini oching" + "Iqtibosni almashtirish" + "Havolani olib tashlang" + "Paragrafni bekor qilish" + "Havola" + "Yozib olish uchun bosib turing" + diff --git a/libraries/troubleshoot/impl/src/main/res/values-pl/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..62d8e0c5d3 --- /dev/null +++ b/libraries/troubleshoot/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,11 @@ + + + "Uruchom testy" + "Uruchom testy ponownie" + "Niektóre testy się nie powiodły. Sprawdź szczegóły." + "Uruchom testy, aby wykryć potencjalne problemy z konfiguracją, jeśli powiadomienia nie działają prawidłowo." + "Spróbuj naprawić" + "Wszystkie testy przebiegły pomyślnie." + "Powiadomienia rozwiązywania problemów" + "Niektóre testy wymagają Twojej uwagi. Sprawdź szczegóły." + 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 b8a46a245b..2227fce81f 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -281,6 +281,9 @@ "Разблакіраваць" "Вы зноў зможаце ўбачыць усе паведамленні." "Разблакіраваць карыстальніка" + "%1$s з %2$s" + "%1$s Замацаваныя паведамленні" + "Паглядзець усе" "Чат" "Падзяліцца месцазнаходжаннем" "Падзяліцца маім месцазнаходжаннем" 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 84358eda6f..39e0610883 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -82,6 +82,7 @@ "OK" "Otevřít nastavení" "Otevřít v aplikaci" + "Pin" "Rychlá odpověď" "Citovat" "Reagovat" @@ -111,6 +112,7 @@ "Vyfotit" "Klepnutím zobrazíte možnosti" "Zkusit znovu" + "Odepnout" "Zobrazit zdroj" "Ano" "O aplikaci" @@ -260,6 +262,10 @@ Důvod: %1$s." "%1$s nemá oprávnění k přístupu k mikrofonu. Povolte přístup k nahrávání hlasové zprávy." "Některé zprávy nebyly odeslány" "Omlouváme se, došlo k chybě" + "Autenticitu této zašifrované zprávy nelze na tomto zařízení zaručit." + "Šifrováno neznámým nebo smazaným zařízením." + "Šifrováno zařízením, které nebylo ověřeno jeho vlastníkem." + "Šifrováno neověřeným uživatelem." "🔐️ Připojte se ke mně na %1$s" "Ahoj, ozvi se mi na %1$s: %2$s" "%1$s Android" @@ -276,6 +282,9 @@ Důvod: %1$s." "Odblokovat" "Znovu uvidíte všechny zprávy od nich." "Odblokovat uživatele" + "%1$s z %2$s" + "%1$s Připnuté zprávy" + "Zobrazit vše" "Chat" "Sdílet polohu" "Sdílet moji polohu" 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 c06e4f8c22..b38211a60d 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -110,6 +110,7 @@ "Τράβηξε φωτογραφία" "Πάτα για επιλογές" "Προσπάθησε ξανά" + "Ξεκαρφίτσωμα" "Προβολή πηγής" "Ναι" "Σχετικά" 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 d82d7cd5ab..a546b18f5d 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -110,6 +110,7 @@ "Tee pilt" "Valikuteks klõpsa" "Proovi uuesti" + "Eemalda kinnitus" "Vaata lähtekoodi" "Jah" "Rakenduse teave" 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 5580f93974..f389f21fa6 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -260,10 +260,14 @@ Powód: %1$s." "%1$s nie ma uprawnień dostępu do Twojego mikrofonu. Włącz dostęp, aby nagrać wiadomość głosową." "Niektóre wiadomości nie zostały wysłane" "Przepraszamy, wystąpił błąd" + "Autentyczność tej wiadomości szyfrowanej nie jest gwarantowana na tym urządzeniu." + "Zaszyfrowana przez nieznane lub usunięte urządzenie." + "Zaszyfrowana przez urządzenie niezweryfikowane przez jego właściciela." + "Zaszyfrowana przez niezweryfikowanego użytkownika." "🔐️ Dołącz do mnie na %1$s" "Hej, porozmawiajmy na %1$s: %2$s" "%1$s Android" - "Gniewne wstrząsanie, aby zgłosić błąd" + "Wstrząśnij gniewnie, aby zgłosić błąd" "Nie udało się wybrać multimediów. Spróbuj ponownie." "Przetwarzanie multimediów do przesłania nie powiodło się, spróbuj ponownie." "Przesyłanie multimediów nie powiodło się, spróbuj ponownie." @@ -272,9 +276,11 @@ Powód: %1$s." "Zablokuj" "Zablokowani użytkownicy nie będą mogli wysyłać Ci wiadomości, a wszystkie ich wiadomości zostaną ukryte. Możesz odblokować ich w dowolnym momencie." "Zablokuj użytkownika" + "Profil" "Odblokuj" "Będziesz mógł ponownie zobaczyć wszystkie wiadomości od tego użytkownika." "Odblokuj użytkownika" + "Czat" "Udostępnij lokalizację" "Udostępnij moją lokalizację" "Otwórz w Apple Maps" 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 10cd8e39cf..17bfd31dc0 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 @@ -1,6 +1,10 @@ "Excluir" + + "%1$d dígito inserido" + "%1$d dígitos inseridos" + "Ocultar senha" "Ir para o final" "Apenas menções" @@ -14,6 +18,10 @@ "Reagir com %1$s" "Reaja com outros emojis" "Lido por %1$s e %2$s" + + "Lido por %1$s e %2$d outro" + "Lido por %1$s e %2$d outros" + "Lido por %1$s" "Toque para mostrar tudo" "Remova a reação com %1$s" @@ -186,7 +194,7 @@ "Sala" "Nome da sala" "por exemplo, o nome do seu projeto" - "Mudanças salvas" + "Alterações salvas" "Salvando" "Bloqueio de tela" "Procurar alguém" @@ -233,8 +241,8 @@ "Erro" "Sucesso" "Aviso" - "Suas mudanças não foram salvas. Tem certeza de que você quer voltar?" - "Salvar mudanças?" + "Suas alterações não foram salvas. Tem certeza de que você quer voltar?" + "Salvar alterações?" "Falha ao criar o link permanente" "%1$s não conseguiu carregar o mapa. Por favor, tente novamente mais tarde." "Falha ao carregar mensagens" @@ -243,6 +251,7 @@ "Mensagem não encontrada" "%1$s não tem permissão para acessar sua localização. Você pode ativar o acesso nas Configurações." "%1$s não tem permissão para acessar sua localização. Habilite o acesso abaixo." + "%1$s não tem permissão para acessar seu microfone. Permita o acesso para gravar uma mensagem de voz." "Algumas mensagens não foram enviadas" "Desculpe, ocorreu um erro" "Criptografada por um dispositivo desconhecido ou apagado." 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 12067cbeaa..253479e53e 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -82,6 +82,7 @@ "Ок" "Открыть настройки" "Открыть с помощью" + "Закрепить" "Быстрый ответ" "Цитата" "Реакция" @@ -111,6 +112,7 @@ "Сделать фото" "Нажмите для просмотра вариантов" "Повторить попытку" + "Открепить" "Показать источник" "Да" "О приложении" @@ -171,6 +173,7 @@ "Ничего не найдено" "Нету названия комнаты" "Не в сети" + "Лицензии с открытым исходным кодом" "или" "Пароль" "Люди" @@ -261,6 +264,10 @@ "%1$s не имеет разрешения на доступ к вашему микрофону. Разрешите доступ к записи голосового сообщения." "Некоторые сообщения не были отправлены" "Извините, произошла ошибка" + "Подлинность этого зашифрованного сообщения не может быть гарантирована на этом устройстве." + "Зашифровано неизвестным или удаленным устройством." + "Зашифровано устройством, не проверенным его владельцем." + "Зашифровано непроверенным пользователем." "🔐️ Присоединяйтесь ко мне в %1$s" "Привет, поговори со мной по %1$s: %2$s" "%1$s Android" @@ -277,6 +284,9 @@ "Разблокировать" "Вы снова сможете увидеть все сообщения." "Разблокировать пользователя" + "%1$s из %2$s" + "%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 1eb3fa1c47..00ad2f5a46 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -112,6 +112,7 @@ "Urobiť fotku" "Klepnutím získate možnosti" "Skúste to znova" + "Odopnúť" "Zobraziť zdroj" "Áno" "O aplikácii" diff --git a/libraries/ui-strings/src/main/res/values-uz/translations.xml b/libraries/ui-strings/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..a80883710c --- /dev/null +++ b/libraries/ui-strings/src/main/res/values-uz/translations.xml @@ -0,0 +1,210 @@ + + + "Oʻchirish" + "Parolni yashirish" + "Faqat eslatmalar" + "Ovozsiz" + "Pauza" + "O\'ynang" + "So\'ro\'vnoma" + "So‘rovnoma yakunlandi" + "Fayllarni yuborish" + "Parolni ko\'rsatish" + "Foydalanuvchi menyusi" + "Ovoz yozishni amalga oshiring" + "Qabul qiling" + "Vaqt jadvaliga qo\'shing" + "Orqaga" + "Bekor qilish" + "Fotosuratni tanlang" + "Tozalash" + "Yopish" + "To\'liq tekshirish" + "Tasdiqlash" + "Davom etish" + "nusxa" + "Havolani nusxalash" + "Havolani xabaraga nusxalash" + "Yaratmoq" + "Xonani yaratish" + "Rad etish" + "Oʻchirish" + "Bajarildi" + "Tahrirlash" + "So‘rovnomani tahrirlash" + "Yoqish" + "So‘rovnomani tugatish" + "Parolni unutdingizmi?" + "Oldinga" + "Taklif qilish" + "Odamlarni taklif qiling" + "Odamlarni taklif qilish%1$s" + "Odamlarni taklif qiling%1$s" + "Takliflar" + "Qo\'shilish" + "Batafsil malumot" + "Tark etish " + "Xonani tark etish " + "Hisobni boshqarish" + "Qurilmalarni boshqarish" + "Keyingisi" + "Yo\'q" + "Hozir emas" + "Ok" + "Sozlamalar" + "Bilan oching" + "Tez javob" + "Iqtibos" + "Reaksiya qilish" + "Ochirish" + "Javob bering" + "Mavzuda javob bering" + "Xato haqida xabar berish" + "Tarkib haqida xabar berish" + "Qayta urinish" + "Shifrni ochishni qayta urinish" + "Saqlash" + "Qidirmoq" + "Yuborish" + "Xabar yuborish" + "Ulashish" + "Havolani ulashing" + "Qaytadan kiring" + "Tizimdan chiqish" + "Baribir tizimdan chiqing" + "Oʻtkazib yuborish" + "Boshlash" + "Suhbatni boshlash" + "Tasdiqlashni boshlang" + "Xaritani yuklash uchun bosing" + "Rasmga olmoq" + "Manbani korish " + "Ha" + "Haqida" + "Qabul qilinadigan foydalanish siyosati" + "Kengaytirilgan sozlamalar" + "Analitika" + "Audio" + "Pufakchalar" + "Chatning zaxira nusxasi" + "Mualliflik huquqi" + "Xona yaratilmoqda…" + "Xonani tark etdi" + "Shifrni ochish xatosi" + "Dasturchi variantlari" + "(tahrirlangan)" + "Tahrirlash" + "*%1$s%2$s" + "Shifrlash yoqilgan" + "Xato" + "Har kim" + "Fayl" + "Fayl “Yuklashlar”ga saqlandi" + "Xabarni yo\'naltirish" + "Surat" + "%1$sga Javob bering" + "APK-ni o\'rnating" + "Ushbu Matrix identifikatori topilmadi, shuning uchun taklif qabul qilinmasligi mumkin." + "Xonadan chiqish" + "Havola vaqtinchalik xotiraga nusxalandi" + "Yuklanmoqda…" + + "%1$d a\'zo" + "%1$d ishtirokchilar" + + "Xabar" + "Xabar tartibi" + "Xabar ochirib tashlandi" + "Zamonaviy" + "Ovozsiz qilish" + "Natijalar yoʻq" + "Oflayn" + "Parol" + "Odamlar" + "Doimiy havola" + "Ruxsat" + "Haqiqatan ham bu soʻrovnomani tugatmoqchimisiz?" + "So‘rov:%1$s" + "Jami ovozlar:%1$s" + "Natijalar soʻrovnoma tugagandan soʻng koʻrsatiladi" + + "%dovoz berish" + "%dovozlar" + + "Maxfiylik siyosati" + "Reaktsiya" + "reaksiyalar" + "Qayta tiklash kaliti" + "Yangilanmoqda…" + "%1$sga Javob berilmoqda" + "Xato haqida xabar bering" + "Hisobot topshirildi" + "Boy matn muharriri" + "Xona nomi" + "masalan, loyihangiz nomi" + "Kimnidir qidiring" + "Qidiruv natijalari" + "Xavfsizlik" + "Yuborilmoqda…" + "Server qo\'llab-quvvatlanmaydi" + "Server URL manzili" + "Sozlamalar" + "Joylashuvi ulashildi" + "Chat boshlanmoqda…" + "Stiker" + "Muvaffaqiyat" + "Tavsiyalar" + "Sinxronlash" + "Matn" + "Uchinchi tomon bildirishnomalari" + "Ip" + "Mavzu" + "Bu xona nima haqida?" + "Shifrni ochish imkonsiz" + "Takliflarni bir yoki bir nechta foydalanuvchiga yuborib bo‘lmadi." + "Taklif(lar)ni yuborib bo‘lmadi" + "Ovozni yoqish" + "Qo\'llab-quvvatlanmagan hodisa" + "Foydalanuvchi nomi" + "Tasdiqlash bekor qilindi" + "Tasdiqlash yakunlandi" + "Video" + "Ovozli xabar" + "Kutilmoqda…" + "Tasdiqlash" + "Xato" + "Muvaffaqiyat" + "Ogohlantirish" + "Doimiy havola yaratilmadi" + "%1$sxaritani yuklay olmadi. Iltimos keyinroq qayta urinib ko\'ring." + "Xabarlar yuklanmadi" + "%1$sjoylashuvingizga kira olmadi. Iltimos keyinroq qayta urinib ko\'ring." + "%1$sjoylashuvingizga kirishga ruxsati yo\'q. Sozlamalar orqali kirishni yoqishingiz mumkin." + "%1$sjoylashuvingizga kirishga ruxsati yo\'q. Quyida kirishni yoqing." + "Bazi xabarlar yuborilmagan" + "Kechirasiz, xatolik yuz berdi" + "🔐️ Menga qo\'shiling%1$s" + "Hey, men bilan gaplash%1$s :%2$s" + "%1$sAndroid" + "Xato haqida xabar berish uchun G\'azablanish" + "Media tanlash jarayonida xatolik yuz berdi, qayta urinib ko\'ring" + "Mediani yuklab bo‘lmadi, qayta urinib ko‘ring." + "Media yuklanmadi, qayta urinib ko‘ring." + "Mediani yuklab bo‘lmadi, qayta urinib ko‘ring." + "Foydalanuvchi tafsilotlarini olinmadi" + "Bloklash" + "Bloklangan foydalanuvchilar sizga xabar yubora olmaydi va ularning barcha xabarlari yashiriladi. Ularni istalgan vaqtda blokdan chiqarishingiz mumkin." + "Foydalanuvchini bloklash" + "Blokdan chiqarish" + "Ulardan kelgan barcha xabarlarni yana koʻrishingiz mumkin boʻladi." + "Foydalanuvchini blokdan chiqarish" + "Joylashuvni ulashish" + "Joylashuvimni ulashing" + "Apple Mapsda oching" + "Google Mapsda oching" + "OpenStreetMapda oching" + "Bu joylashuvni ulashing" + "Joylashuv" + "Versiya:%1$s (%2$s )" + "en" + diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index c5d8f46622..a86f920ed9 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -110,6 +110,7 @@ "Take photo" "Tap for options" "Try again" + "Unpin" "View source" "Yes" "About" diff --git a/plugins/src/main/kotlin/extension/locales.kt b/plugins/src/main/kotlin/extension/locales.kt index 18cd3d5531..fcbfedf852 100644 --- a/plugins/src/main/kotlin/extension/locales.kt +++ b/plugins/src/main/kotlin/extension/locales.kt @@ -24,6 +24,7 @@ val locales = setOf( "sk", "sv", "uk", + "uz", "zh-rCN", "zh-rTW", ) diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_1_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_1_de.png index 1e2a6627e9..147fc99887 100644 --- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_1_de.png +++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e190af91f08cdebf55b8b1567edf71ac652b0501329853708e033d18ad4d805 -size 109003 +oid sha256:7d233e3dedc7fd2e0876243e250c24e2cf5e3bfa7ade8f3615c641e781c04ad0 +size 113116 diff --git a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_0_de.png b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_0_de.png index 495ecadf09..8de7a0fc01 100644 --- a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_0_de.png +++ b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c52735432835df48912fe46bd060f29b67a4c0f26149d133972f1de3a2a29d10 -size 52410 +oid sha256:9ba32509532bfe046feff840c2cb1d3278690fb89797e4d12710c6d0c708d672 +size 61476 diff --git a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_1_de.png b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_1_de.png index 495ecadf09..8de7a0fc01 100644 --- a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_1_de.png +++ b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c52735432835df48912fe46bd060f29b67a4c0f26149d133972f1de3a2a29d10 -size 52410 +oid sha256:9ba32509532bfe046feff840c2cb1d3278690fb89797e4d12710c6d0c708d672 +size 61476 diff --git a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_2_de.png b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_2_de.png index 0aafaef26b..dc4b32c96a 100644 --- a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_2_de.png +++ b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2b6105201164499016f4ca00915ae18cbe427416f3c22cd55ea26f7907c8cea -size 50143 +oid sha256:387890a1fc4f01d5ee76d702a69eeb955010c0b8d6f8adc4a5f2879d8ba50837 +size 59229 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 76259f7913..4c3d1bdcde 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,40 +1,40 @@ // 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",19923,], -["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19926,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19929,], +["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19929,], ["features.invite.impl.response_AcceptDeclineInviteView_Day_0_en","features.invite.impl.response_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19923,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19923,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19923,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19923,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19929,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19929,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19929,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19929,], ["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_4_en","features.login.impl.accountprovider_AccountProviderView_Night_4_en",0,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19923,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19923,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19923,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19923,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19923,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19923,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19923,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19923,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19923,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19923,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19923,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19923,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19929,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19929,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19929,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19929,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19929,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19929,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19929,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19929,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19929,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19929,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19929,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19929,], ["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",19923,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",19929,], ["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",19923,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",19929,], ["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",19923,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",19929,], ["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",19923,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19929,], ["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,], @@ -44,11 +44,11 @@ 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","",19923,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19923,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19923,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19923,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19923,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",19929,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19929,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19929,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19929,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19929,], ["libraries.designsystem.components.avatar_Avatar_Avatars_0_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_10_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_11_en","",0,], @@ -128,13 +128,13 @@ export const screenshots = [ ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], ["libraries.designsystem.components_BigCheckmark_Day_0_en","libraries.designsystem.components_BigCheckmark_Night_0_en",0,], ["libraries.designsystem.components_BigIcon_Day_0_en","libraries.designsystem.components_BigIcon_Night_0_en",0,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19923,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19923,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19923,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19923,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19923,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19923,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19923,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19929,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19929,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19929,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19929,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19929,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19929,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19929,], ["libraries.designsystem.components_BloomInitials_Day_0_en","libraries.designsystem.components_BloomInitials_Night_0_en",0,], ["libraries.designsystem.components_BloomInitials_Day_1_en","libraries.designsystem.components_BloomInitials_Night_1_en",0,], ["libraries.designsystem.components_BloomInitials_Day_2_en","libraries.designsystem.components_BloomInitials_Night_2_en",0,], @@ -145,84 +145,84 @@ export const screenshots = [ ["libraries.designsystem.components_BloomInitials_Day_7_en","libraries.designsystem.components_BloomInitials_Night_7_en",0,], ["libraries.designsystem.components_Bloom_Day_0_en","libraries.designsystem.components_Bloom_Night_0_en",0,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19923,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19923,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19923,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19923,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19923,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19929,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19929,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19929,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19929,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19929,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_0_en","features.call.impl.ui_CallScreenPipView_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_1_en","features.call.impl.ui_CallScreenPipView_Night_1_en",0,], ["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,], -["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19923,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19923,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19923,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19923,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19923,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19923,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19923,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19923,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19923,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19923,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19923,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19929,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19929,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19929,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19929,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19929,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19929,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19929,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19929,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19929,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19929,], ["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",19923,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19923,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",19929,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19929,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19923,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19929,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], ["libraries.textcomposer.components_ComposerOptionsButton_Day_0_en","libraries.textcomposer.components_ComposerOptionsButton_Night_0_en",0,], ["libraries.designsystem.components.avatar_CompositeAvatar_Avatars_en","",0,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19923,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19923,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19929,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19929,], ["features.preferences.impl.developer.tracing_ConfigureTracingView_Day_0_en","features.preferences.impl.developer.tracing_ConfigureTracingView_Night_0_en",0,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19923,], -["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19923,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19929,], +["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19929,], ["libraries.designsystem.components.dialogs_ConfirmationDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ConfirmationDialog_Day_0_en","libraries.designsystem.components.dialogs_ConfirmationDialog_Night_0_en",0,], ["features.networkmonitor.api.ui_ConnectivityIndicatorView_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicatorView_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19923,], -["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19923,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19923,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19923,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19923,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19923,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19923,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19923,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19923,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19923,], -["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19923,], -["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19923,], -["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19923,], -["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19923,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19923,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19923,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19929,], +["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19929,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19929,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19929,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19929,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19929,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19929,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19929,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19929,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19929,], +["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19929,], +["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19929,], +["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19929,], +["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19929,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19929,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19929,], ["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",19923,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19923,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19923,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",19929,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19929,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19929,], ["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",19923,], -["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19923,], -["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19923,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19923,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19923,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19923,], -["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19923,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",19929,], +["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19929,], +["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19929,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19929,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19929,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19929,], +["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19929,], ["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,], @@ -234,12 +234,12 @@ export const screenshots = [ ["libraries.designsystem.text_DpScale_1_0f__en","",0,], ["libraries.designsystem.text_DpScale_1_5f__en","",0,], ["libraries.designsystem.theme.components_DropdownMenuItem_Menus_en","",0,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19923,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19923,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19923,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19923,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19923,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19923,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19929,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19929,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19929,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19929,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19929,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19929,], ["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,], @@ -249,10 +249,10 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiPicker_Night_0_en",0,], -["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19923,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19923,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19923,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19923,], +["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19929,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19929,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19929,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19929,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], ["libraries.designsystem.theme.components_FilledButtonLargeLowPadding_Buttons_en","",0,], @@ -263,15 +263,15 @@ export const screenshots = [ ["libraries.designsystem.theme.components_FloatingActionButton_Floating Action Buttons_en","",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19923,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19923,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19923,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19929,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19929,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19929,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_0_en","features.messages.impl.forward_ForwardMessagesView_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_1_en","features.messages.impl.forward_ForwardMessagesView_Night_1_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_2_en","features.messages.impl.forward_ForwardMessagesView_Night_2_en",0,], -["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19923,], -["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19923,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19929,], +["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19929,], ["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,], @@ -284,8 +284,8 @@ export const screenshots = [ ["libraries.designsystem.atomic.molecules_IconTitleSubtitleMoleculeWithResIcon_Day_0_en","libraries.designsystem.atomic.molecules_IconTitleSubtitleMoleculeWithResIcon_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_IconTitleSubtitleMolecule_Day_0_en","libraries.designsystem.atomic.molecules_IconTitleSubtitleMolecule_Night_0_en",0,], ["libraries.designsystem.theme.components_IconToggleButton_Toggles_en","",0,], -["appicon.enterprise_Icon_en","",0,], ["appicon.element_Icon_en","",0,], +["appicon.enterprise_Icon_en","",0,], ["libraries.designsystem.icons_IconsCompound_Day_0_en","libraries.designsystem.icons_IconsCompound_Night_0_en",0,], ["libraries.designsystem.icons_IconsCompound_Day_1_en","libraries.designsystem.icons_IconsCompound_Night_1_en",0,], ["libraries.designsystem.icons_IconsCompound_Day_2_en","libraries.designsystem.icons_IconsCompound_Night_2_en",0,], @@ -298,37 +298,37 @@ 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",19923,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",19929,], ["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",19923,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",19929,], ["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",19923,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",19929,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19923,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19929,], ["features.joinroom.impl_JoinRoomView_Day_0_en","features.joinroom.impl_JoinRoomView_Night_0_en",0,], ["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",0,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19923,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19923,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19923,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19923,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19923,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19923,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19923,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19923,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19923,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19929,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19929,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19929,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19929,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19929,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19929,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19929,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19929,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19929,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["libraries.designsystem.components_LabelledOutlinedTextField_Day_0_en","libraries.designsystem.components_LabelledOutlinedTextField_Night_0_en",0,], ["libraries.designsystem.components_LabelledTextField_Day_0_en","libraries.designsystem.components_LabelledTextField_Night_0_en",0,], ["features.leaveroom.api_LeaveRoomView_Day_0_en","features.leaveroom.api_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19923,], -["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19923,], -["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19923,], -["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19923,], -["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19923,], -["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19923,], +["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19929,], +["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19929,], +["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19929,], +["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19929,], +["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19929,], +["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19929,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], @@ -379,28 +379,28 @@ 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",19923,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19923,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19923,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19923,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19929,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19929,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19929,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19929,], ["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",19923,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19923,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19923,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19923,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19923,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19923,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19923,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19923,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19923,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19923,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19923,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19923,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19923,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19923,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19923,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",19929,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19929,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19929,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19929,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19929,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19929,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19929,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19929,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19929,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19929,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19929,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19929,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19929,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19929,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19929,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19923,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19929,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en","libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_0_en","libraries.matrix.ui.components_MatrixUserHeader_Night_0_en",0,], @@ -410,7 +410,7 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_10_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19923,], +["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19929,], ["libraries.mediaviewer.api.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_5_en","",0,], @@ -420,10 +420,10 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_9_en","",0,], ["libraries.designsystem.theme.components_MediumTopAppBar_App Bars_en","",0,], ["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,], -["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19923,], +["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19929,], ["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",19923,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",19929,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_10_en","features.messages.impl.timeline.components_MessageEventBubble_Night_10_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_11_en","features.messages.impl.timeline.components_MessageEventBubble_Night_11_en",0,], @@ -447,25 +447,25 @@ 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.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19923,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19923,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19929,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19929,], ["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",0,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19923,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19923,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19923,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19923,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19929,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19929,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19929,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19929,], ["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",0,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19923,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19923,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19923,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19923,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19923,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19923,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19923,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19923,], -["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19923,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19929,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19929,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19929,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19929,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19929,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19929,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19929,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19929,], +["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19929,], ["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",19923,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",19929,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -474,28 +474,28 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple selection List item - selection in trailing content_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple selection List item - selection in supporting text_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple selection List item - no selection_List items_en","",0,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19923,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19923,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19929,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19929,], ["features.login.impl.oidc.webview_OidcView_Day_0_en","features.login.impl.oidc.webview_OidcView_Night_0_en",0,], ["features.login.impl.oidc.webview_OidcView_Day_1_en","features.login.impl.oidc.webview_OidcView_Night_1_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19923,], -["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19923,], -["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19923,], -["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19923,], -["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19923,], +["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19929,], +["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19929,], +["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19929,], +["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19929,], +["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19929,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], @@ -510,47 +510,47 @@ export const screenshots = [ ["libraries.designsystem.components_PageTitleWithIconFull_Day_3_en","libraries.designsystem.components_PageTitleWithIconFull_Night_3_en",0,], ["libraries.designsystem.components_PageTitleWithIconFull_Day_4_en","libraries.designsystem.components_PageTitleWithIconFull_Night_4_en",0,], ["libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en","libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en",0,], -["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19923,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19923,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19923,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19923,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19929,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19929,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19929,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19929,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19929,], ["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",19923,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19923,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19929,], ["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",19923,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19923,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19923,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19923,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19923,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19929,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19929,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19929,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19929,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19929,], ["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",19923,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19923,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19923,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19923,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19923,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19923,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19923,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19923,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19923,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19923,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19923,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",19929,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19929,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19929,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19929,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19929,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19929,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19929,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19929,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19929,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19929,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19929,], ["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceDivider_Preferences_en","",0,], @@ -566,182 +566,182 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceTextLight_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19923,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19923,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19923,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19923,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19929,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19929,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19929,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19929,], ["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","",19923,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19923,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19923,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19923,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19923,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19923,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19923,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19923,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19923,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19923,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19923,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19923,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19923,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19923,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19923,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19923,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19923,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19923,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",19929,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19929,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19929,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19929,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19929,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19929,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19929,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19929,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19929,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19929,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19929,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19929,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19929,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19929,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19929,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19929,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19929,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19929,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19923,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19923,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19929,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19929,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19923,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19923,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19923,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19923,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19923,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19923,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19923,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19929,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19929,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19929,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19929,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19929,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19929,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19929,], ["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",19923,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19923,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19923,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19923,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19923,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19923,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19923,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19923,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19923,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19923,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19923,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19923,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19923,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19923,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19923,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19923,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19929,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19929,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19929,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19929,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19929,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19929,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19929,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19929,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19929,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19929,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19929,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19929,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19929,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19929,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19929,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19929,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19923,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19929,], ["features.roomdetails.impl.components_RoomBadgeNegative_Day_0_en","features.roomdetails.impl.components_RoomBadgeNegative_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgeNeutral_Day_0_en","features.roomdetails.impl.components_RoomBadgeNeutral_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgePositive_Day_0_en","features.roomdetails.impl.components_RoomBadgePositive_Night_0_en",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",19923,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",19923,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19923,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19923,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19923,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19923,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19923,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19923,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19923,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19923,], -["features.roomdetails.impl_RoomDetails_0_en","",19923,], -["features.roomdetails.impl_RoomDetails_10_en","",19923,], -["features.roomdetails.impl_RoomDetails_11_en","",19923,], -["features.roomdetails.impl_RoomDetails_12_en","",19923,], -["features.roomdetails.impl_RoomDetails_1_en","",19923,], -["features.roomdetails.impl_RoomDetails_2_en","",19923,], -["features.roomdetails.impl_RoomDetails_3_en","",19923,], -["features.roomdetails.impl_RoomDetails_4_en","",19923,], -["features.roomdetails.impl_RoomDetails_5_en","",19923,], -["features.roomdetails.impl_RoomDetails_6_en","",19923,], -["features.roomdetails.impl_RoomDetails_7_en","",19923,], -["features.roomdetails.impl_RoomDetails_8_en","",19923,], -["features.roomdetails.impl_RoomDetails_9_en","",19923,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19923,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19923,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19923,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19923,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19923,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19923,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19923,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19923,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19923,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19923,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19923,], -["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19923,], -["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19923,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",19929,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",19929,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19929,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19929,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19929,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19929,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19929,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19929,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19929,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19929,], +["features.roomdetails.impl_RoomDetails_0_en","",19929,], +["features.roomdetails.impl_RoomDetails_10_en","",19929,], +["features.roomdetails.impl_RoomDetails_11_en","",19929,], +["features.roomdetails.impl_RoomDetails_12_en","",19929,], +["features.roomdetails.impl_RoomDetails_1_en","",19929,], +["features.roomdetails.impl_RoomDetails_2_en","",19929,], +["features.roomdetails.impl_RoomDetails_3_en","",19929,], +["features.roomdetails.impl_RoomDetails_4_en","",19929,], +["features.roomdetails.impl_RoomDetails_5_en","",19929,], +["features.roomdetails.impl_RoomDetails_6_en","",19929,], +["features.roomdetails.impl_RoomDetails_7_en","",19929,], +["features.roomdetails.impl_RoomDetails_8_en","",19929,], +["features.roomdetails.impl_RoomDetails_9_en","",19929,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19929,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19929,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19929,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19929,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19929,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19929,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19929,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19929,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19929,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19929,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19929,], +["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19929,], +["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19929,], ["features.roomlist.impl.components_RoomListContentView_Day_2_en","features.roomlist.impl.components_RoomListContentView_Night_2_en",0,], -["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19923,], -["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19923,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19923,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19923,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19923,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19923,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19923,], +["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19929,], +["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19929,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19929,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19929,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19929,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19929,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19929,], ["features.roomlist.impl.search_RoomListSearchContent_Day_0_en","features.roomlist.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19923,], -["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19923,], -["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19923,], +["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19929,], +["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19929,], +["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19929,], ["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",0,], -["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19923,], -["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19923,], -["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19923,], -["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19923,], -["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19923,], -["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19923,], -["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19923,], +["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19929,], +["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19929,], +["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19929,], +["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19929,], +["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19929,], +["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19929,], +["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19929,], ["features.roomlist.impl_RoomListView_Day_8_en","features.roomlist.impl_RoomListView_Night_8_en",0,], -["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19923,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19923,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19923,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19923,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19923,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19923,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19923,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19923,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19923,], +["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19929,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19929,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19929,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19929,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19929,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19929,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19929,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19929,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19929,], ["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19923,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19923,], -["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19926,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19929,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19929,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19929,], ["libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Day_0_en","libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Night_0_en",0,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19923,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19923,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19923,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19923,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19923,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19923,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19923,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19923,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19923,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19929,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19929,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19929,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19929,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19929,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19929,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19929,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19929,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19929,], ["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_9_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19923,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19923,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19923,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19923,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19923,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19923,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19923,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19923,], -["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19923,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19923,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19923,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19923,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19923,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19923,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19923,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19929,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19929,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19929,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19929,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19929,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19929,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19929,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19929,], +["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19929,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19929,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19929,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19929,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19929,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19929,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19929,], ["features.roomlist.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.roomlist.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_0_en","features.roomlist.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_10_en","features.roomlist.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -764,10 +764,10 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_26_en","features.roomlist.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_27_en","features.roomlist.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_28_en","features.roomlist.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19923,], -["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19923,], -["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19923,], -["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19923,], +["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19929,], +["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19929,], +["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19929,], +["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19929,], ["features.roomlist.impl.components_RoomSummaryRow_Day_3_en","features.roomlist.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_4_en","features.roomlist.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_5_en","features.roomlist.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -775,64 +775,64 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_7_en","features.roomlist.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_8_en","features.roomlist.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_9_en","features.roomlist.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19923,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19923,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19923,], -["appicon.enterprise_RoundIcon_en","",0,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19929,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19929,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19929,], ["appicon.element_RoundIcon_en","",0,], +["appicon.enterprise_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",19923,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19923,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19923,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",19929,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19929,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19929,], ["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","",19923,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search views_en","",19929,], ["libraries.designsystem.theme.components_SearchBarActiveWithQueryNoBackButton_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithQuery_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarInactive_Search views_en","",0,], -["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19923,], -["features.createroom.impl.components_SearchSingleUserResultItem_en","",19923,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19923,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19923,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19923,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19923,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19923,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19923,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19923,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19923,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19923,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19923,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19923,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19923,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19923,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19923,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19923,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19923,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19923,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19923,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19923,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19923,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19923,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19923,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19923,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19923,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19923,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19923,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19923,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19923,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19923,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19923,], +["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19929,], +["features.createroom.impl.components_SearchSingleUserResultItem_en","",19929,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19929,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19929,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19929,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19929,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19929,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19929,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19929,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19929,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19929,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19929,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19929,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19929,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19929,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19929,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19929,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19929,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19929,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19929,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19929,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19929,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19929,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19929,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19929,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19929,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19929,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19929,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19929,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19929,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19929,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19929,], ["libraries.matrix.ui.components_SelectedRoom_Day_0_en","libraries.matrix.ui.components_SelectedRoom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoom_Day_1_en","libraries.matrix.ui.components_SelectedRoom_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en","libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUser_Day_0_en","libraries.matrix.ui.components_SelectedUser_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19923,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19923,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19923,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19923,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19923,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19929,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19929,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19929,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19929,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19929,], ["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,], @@ -842,37 +842,37 @@ 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.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19923,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19923,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19923,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19923,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19923,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19923,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19929,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19929,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19929,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19929,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19929,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19929,], ["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",19923,], -["features.messages.impl.actionlist_SheetContent_Day_0_en","features.messages.impl.actionlist_SheetContent_Night_0_en",0,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",19929,], ["features.messages.impl.timeline.components.reactionsummary_SheetContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_SheetContent_Night_0_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19923,], +["features.messages.impl.actionlist_SheetContent_Day_0_en","features.messages.impl.actionlist_SheetContent_Night_0_en",0,], +["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19929,], ["features.messages.impl.actionlist_SheetContent_Day_1_en","features.messages.impl.actionlist_SheetContent_Night_1_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19923,], -["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19923,], -["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19923,], -["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19923,], -["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19923,], -["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19923,], -["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19923,], -["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19923,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19923,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19923,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19923,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19923,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19923,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19923,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19923,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19923,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19923,], +["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19929,], +["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19929,], +["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19929,], +["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19929,], +["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19929,], +["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19929,], +["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19929,], +["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19929,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19929,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19929,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19929,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19929,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19929,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19929,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19929,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19929,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19929,], ["libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en",0,], ["libraries.designsystem.components.list_SingleSelectionListItemCustomFormattert_Single selection List item - custom formatter_List items_en","",0,], @@ -881,7 +881,7 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single selection List item - no selection, supporting text_List items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single selection List item - no selection_List items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19923,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19929,], ["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,], @@ -891,36 +891,36 @@ export const screenshots = [ ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], ["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",0,], -["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19923,], +["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19929,], ["features.location.api_StaticMapView_Day_0_en","features.location.api_StaticMapView_Night_0_en",0,], ["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",19923,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",19929,], ["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_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19923,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19923,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19923,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19923,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19923,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19923,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19923,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19929,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19929,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19929,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19929,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19929,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19929,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19929,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], ["libraries.designsystem.theme.components_TextFieldDark_TextFields_en","",0,], @@ -932,38 +932,38 @@ export const screenshots = [ ["libraries.designsystem.theme.components_TextFieldValueTextFieldDark_TextFields_en","",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19923,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19923,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19923,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19929,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19929,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19929,], ["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",19923,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19923,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",19929,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19929,], ["features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en",0,], ["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_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19923,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19929,], ["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",19923,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19923,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19923,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",19929,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19929,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19929,], ["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,], ["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",19923,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19923,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19923,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19929,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19929,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19929,], ["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",19923,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19923,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",19929,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19929,], ["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,], @@ -972,36 +972,36 @@ 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",19923,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19929,], ["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",19923,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19929,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19923,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19929,], ["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_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19923,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19923,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19929,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19929,], ["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_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",19923,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",19929,], ["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",19923,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19923,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19923,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19923,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19923,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19929,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19929,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19929,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19929,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19929,], ["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",19923,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19923,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",19929,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19929,], ["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",19923,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",19929,], ["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,], @@ -1010,8 +1010,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",19923,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19923,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",19929,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19929,], ["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,], @@ -1023,7 +1023,7 @@ 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",19923,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",19929,], ["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,], @@ -1045,79 +1045,79 @@ 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_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19923,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19929,], ["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",19923,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19923,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19923,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19923,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19923,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19923,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19923,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19929,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19929,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19929,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19929,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19929,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19929,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19929,], ["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",19923,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",19929,], ["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",19923,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",19929,], ["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",19923,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",19929,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.theme.components_TopAppBar_App Bars_en","",0,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19923,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19923,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19923,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19923,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19923,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19923,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19923,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19923,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19929,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19929,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19929,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19929,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19929,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19929,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19929,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19929,], ["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",19923,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19923,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19923,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19923,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19923,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19923,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",19929,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19929,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19929,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19929,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19929,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19929,], ["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","",19923,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",19929,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19923,], -["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19923,], -["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19923,], -["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19923,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19929,], +["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19929,], +["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19929,], +["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19929,], ["features.createroom.impl.components_UserListView_Day_3_en","features.createroom.impl.components_UserListView_Night_3_en",0,], ["features.createroom.impl.components_UserListView_Day_4_en","features.createroom.impl.components_UserListView_Night_4_en",0,], ["features.createroom.impl.components_UserListView_Day_5_en","features.createroom.impl.components_UserListView_Night_5_en",0,], ["features.createroom.impl.components_UserListView_Day_6_en","features.createroom.impl.components_UserListView_Night_6_en",0,], -["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19923,], +["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19929,], ["features.createroom.impl.components_UserListView_Day_8_en","features.createroom.impl.components_UserListView_Night_8_en",0,], -["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19923,], +["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19929,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], ["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",0,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19923,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19923,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19923,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19923,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19923,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19923,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19923,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19923,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19923,], -["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19923,], -["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19923,], -["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19923,], -["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19923,], -["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19923,], -["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19923,], -["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19923,], -["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19923,], -["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19923,], -["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19923,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19929,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19929,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19929,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19929,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19929,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19929,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19929,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19929,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19929,], +["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19929,], +["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19929,], +["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19929,], +["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19929,], +["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19929,], +["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19929,], +["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19929,], +["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19929,], +["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19929,], +["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19929,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,], @@ -1131,12 +1131,12 @@ export const screenshots = [ ["libraries.textcomposer.components_VoiceMessageRecorderButton_Day_0_en","libraries.textcomposer.components_VoiceMessageRecorderButton_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessageRecording_Day_0_en","libraries.textcomposer.components_VoiceMessageRecording_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessage_Day_0_en","libraries.textcomposer.components_VoiceMessage_Night_0_en",0,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19923,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19923,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19923,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19923,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19923,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19929,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19929,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19929,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19929,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19929,], ["libraries.designsystem.components.media_WaveformPlaybackView_Day_0_en","libraries.designsystem.components.media_WaveformPlaybackView_Night_0_en",0,], -["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19923,], +["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19929,], ["libraries.designsystem.ruler_WithRulers_Day_0_en","libraries.designsystem.ruler_WithRulers_Night_0_en",0,], ]; From 685261e1fb7a06ca3c79627c090ad3e8921b7049 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 08:58:17 +0200 Subject: [PATCH 027/186] Update media3 to v1.4.0 (#3247) 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 0609a17dc2..585749f79a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,7 @@ constraintlayout = "2.1.4" constraintlayout_compose = "1.0.1" lifecycle = "2.7.0" activity = "1.9.1" -media3 = "1.3.1" +media3 = "1.4.0" camera = "1.3.4" # Compose From 776116550e7e5a1a5c88bb63c0046ae27507815e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 09:48:34 +0200 Subject: [PATCH 028/186] Update dependency androidx.annotation:annotation-jvm to v1.8.1 (#3243) 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 585749f79a..1cca10860b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -75,7 +75,7 @@ oss_licenses_plugin = "com.google.android.gms:oss-licenses-plugin:0.10.6" # AndroidX androidx_core = { module = "androidx.core:core", version.ref = "core" } androidx_corektx = { module = "androidx.core:core-ktx", version.ref = "core" } -androidx_annotationjvm = "androidx.annotation:annotation-jvm:1.8.0" +androidx_annotationjvm = "androidx.annotation:annotation-jvm:1.8.1" androidx_datastore_preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" } androidx_datastore_datastore = { module = "androidx.datastore:datastore", version.ref = "datastore" } androidx_exifinterface = "androidx.exifinterface:exifinterface:1.3.7" From bcb44158b656a91afad31ffe261c27fe33c8a21e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 09:51:34 +0200 Subject: [PATCH 029/186] Update dependencyAnalysis to v1.33.0 (#3250) 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 1cca10860b..e784f9bb6a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ test_core = "1.6.1" #other coil = "2.7.0" datetime = "0.6.0" -dependencyAnalysis = "1.32.0" +dependencyAnalysis = "1.33.0" serialization_json = "1.6.3" showkase = "1.0.3" appyx = "1.4.0" From ba123ccee1c8f9047b1633fac25fe962bb2ac2ff Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 29 Jul 2024 11:09:57 +0200 Subject: [PATCH 030/186] Rust sdk update : fix test --- .../matrix/impl/roomlist/RoomSummaryListProcessorTest.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 f2e2f07ad6..33d8a94bb5 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 @@ -221,6 +221,7 @@ private fun aRustRoomInfo( numUnreadMessages: ULong = 0uL, numUnreadNotifications: ULong = 0uL, numUnreadMentions: ULong = 0uL, + pinnedEventIds: List = listOf(), ) = RoomInfo( id = id, displayName = displayName, @@ -249,7 +250,8 @@ private fun aRustRoomInfo( isMarkedUnread = isMarkedUnread, numUnreadMessages = numUnreadMessages, numUnreadNotifications = numUnreadNotifications, - numUnreadMentions = numUnreadMentions + numUnreadMentions = numUnreadMentions, + pinnedEventIds = pinnedEventIds, ) class FakeRoomListItem( From 52a643f116b6ffee3cca7f7aaa9cd7e4c70bbdc5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 29 Jul 2024 12:50:35 +0200 Subject: [PATCH 031/186] Pin : expose the new rust sdk apis --- .../libraries/matrix/api/room/MatrixRoom.kt | 2 ++ .../matrix/api/room/MatrixRoomInfo.kt | 2 ++ .../libraries/matrix/api/timeline/Timeline.kt | 19 +++++++++++++++++++ .../matrix/impl/room/MatrixRoomInfoMapper.kt | 4 +++- .../matrix/impl/room/RustMatrixRoom.kt | 6 ++++++ .../matrix/impl/timeline/RustTimeline.kt | 12 ++++++++++++ .../matrix/test/room/FakeMatrixRoom.kt | 7 +++++++ .../matrix/test/timeline/FakeTimeline.kt | 11 +++++++++++ 8 files changed, 62 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 378ada5b16..76c9f902c7 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -180,6 +180,8 @@ interface MatrixRoom : Closeable { suspend fun canUserTriggerRoomNotification(userId: UserId): Result + suspend fun canUserPinUnpin(userId: UserId): Result + suspend fun canUserJoinCall(userId: UserId): Result = canUserSendState(userId, StateEventType.CALL_MEMBER) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt index 70da8e7364..c7de03dac6 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt @@ -17,6 +17,7 @@ package io.element.android.libraries.matrix.api.room import androidx.compose.runtime.Immutable +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId @@ -52,4 +53,5 @@ data class MatrixRoomInfo( val hasRoomCall: Boolean, val activeRoomCallParticipants: ImmutableList, val heroes: ImmutableList, + val pinnedEventIds: ImmutableList ) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt index 3d8defa252..eb2fbe9a30 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt @@ -169,4 +169,23 @@ interface Timeline : AutoCloseable { ): Result suspend fun loadReplyDetails(eventId: EventId): InReplyTo + + /** + * Adds a new pinned event by sending an updated `m.room.pinned_events` + * event containing the new event id. + * + * Returns `true` if we sent the request, `false` if the event was already + * pinned. + */ + suspend fun pinEvent(eventId: EventId): Result + + /** + * Adds a new pinned event by sending an updated `m.room.pinned_events` + * event without the event id we want to remove. + * + * Returns `true` if we sent the request, `false` if the event wasn't + * pinned + */ + suspend fun unpinEvent(eventId: EventId): Result + } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt index 6a87b02a2b..a7461d6b0a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.impl.room +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId @@ -58,7 +59,8 @@ class MatrixRoomInfoMapper { userDefinedNotificationMode = it.userDefinedNotificationMode?.map(), hasRoomCall = it.hasRoomCall, activeRoomCallParticipants = it.activeRoomCallParticipants.toImmutableList(), - heroes = it.elementHeroes().toImmutableList() + heroes = it.elementHeroes().toImmutableList(), + pinnedEventIds = it.pinnedEventIds.map(::EventId).toImmutableList(), ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index b594bba5e4..96beb99d5a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -403,6 +403,12 @@ class RustMatrixRoom( } } + override suspend fun canUserPinUnpin(userId: UserId): Result { + return runCatching { + innerRoom.canUserPinUnpin(userId.value) + } + } + override suspend fun sendImage( file: File, thumbnailFile: File?, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index b57efc5603..87fca3d395 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -525,6 +525,18 @@ class RustTimeline( } } + override suspend fun pinEvent(eventId: EventId): Result = withContext(dispatcher) { + runCatching { + inner.pinEvent(eventId = eventId.value) + } + } + + override suspend fun unpinEvent(eventId: EventId): Result = withContext(dispatcher) { + runCatching { + inner.unpinEvent(eventId = eventId.value) + } + } + private suspend fun fetchDetailsForEvent(eventId: EventId): Result { return runCatching { inner.fetchDetailsForEvent(eventId.value) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index cfd0267516..e2be5bcb66 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -125,6 +125,7 @@ class FakeMatrixRoom( private val getWidgetDriverResult: (MatrixWidgetSettings) -> 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 powerLevelsResult: () -> Result = { lambdaError() }, private val updatePowerLevelsResult: () -> Result = { lambdaError() }, @@ -289,6 +290,10 @@ class FakeMatrixRoom( return canUserJoinCallResult(userId) } + override suspend fun canUserPinUnpin(userId: UserId): Result { + return canUserPinUnpinResult(userId) + } + override suspend fun sendImage( file: File, thumbnailFile: File?, @@ -517,6 +522,7 @@ fun aRoomInfo( userPowerLevels: ImmutableMap = persistentMapOf(), activeRoomCallParticipants: List = emptyList(), heroes: List = emptyList(), + pinnedEventIds: List = emptyList(), ) = MatrixRoomInfo( id = id, name = name, @@ -542,6 +548,7 @@ fun aRoomInfo( userPowerLevels = userPowerLevels, activeRoomCallParticipants = activeRoomCallParticipants.toImmutableList(), heroes = heroes.toImmutableList(), + pinnedEventIds = pinnedEventIds.toImmutableList(), ) fun defaultRoomPowerLevels() = MatrixRoomPowerLevels( diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt index 4fa9f7a94c..6216c7b182 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt @@ -33,6 +33,7 @@ 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.InReplyTo import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler +import io.element.android.tests.testutils.lambda.lambdaError import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -371,6 +372,16 @@ class FakeTimeline( override suspend fun loadReplyDetails(eventId: EventId) = loadReplyDetailsLambda(eventId) + var pinEventLambda: (eventId: EventId) -> Result = lambdaError() + override suspend fun pinEvent(eventId: EventId): Result { + return pinEventLambda(eventId) + } + + var unpinEventLambda: (eventId: EventId) -> Result = lambdaError() + override suspend fun unpinEvent(eventId: EventId): Result { + return unpinEventLambda(eventId) + } + var closeCounter = 0 private set From 210e2092cdb5acd52697f47ee039da1355262753 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 29 Jul 2024 13:43:47 +0200 Subject: [PATCH 032/186] Refactor userEventPermissions --- .../messages/impl/MessagesPresenter.kt | 30 ++++++++----------- .../messages/impl/MessagesStateProvider.kt | 2 +- .../messages/impl/UserEventPermissions.kt | 14 +++++++-- .../impl/actionlist/ActionListPresenter.kt | 4 +-- .../messages/impl/MessagesViewTest.kt | 3 +- .../room/powerlevels/MatrixRoomPowerLevels.kt | 5 ++++ .../matrix/ui/room/MatrixRoomState.kt | 7 +++++ 7 files changed, 41 insertions(+), 24 deletions(-) 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 16698d7e34..c86b587063 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 @@ -25,6 +25,7 @@ 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 @@ -74,12 +75,13 @@ import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState 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.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.ui.messages.reply.map import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.room.canCall -import io.element.android.libraries.matrix.ui.room.canRedactOtherAsState -import io.element.android.libraries.matrix.ui.room.canRedactOwnAsState -import io.element.android.libraries.matrix.ui.room.canSendMessageAsState import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.toPersistentList @@ -234,20 +236,14 @@ class MessagesPresenter @AssistedInject constructor( @Composable private fun userEventPermissions(updateKey: Long): State { - val userHasPermissionToSendMessage by room.canSendMessageAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = updateKey) - val userHasPermissionToRedactOwn by room.canRedactOwnAsState(updateKey = updateKey) - val userHasPermissionToRedactOther by room.canRedactOtherAsState(updateKey = updateKey) - val userHasPermissionToSendReaction by room.canSendMessageAsState(type = MessageEventType.REACTION, updateKey = updateKey) - return remember { - derivedStateOf { - UserEventPermissions( - canSendMessage = userHasPermissionToSendMessage, - canRedactOwn = userHasPermissionToRedactOwn, - canRedactOther = userHasPermissionToRedactOther, - canSendReaction = userHasPermissionToSendReaction, - canPin = false, - ) - } + return produceState(UserEventPermissions.DEFAULT, key1 = updateKey) { + value = UserEventPermissions( + canSendMessage = room.canSendMessage(type = MessageEventType.ROOM_MESSAGE).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 }, + ) } } 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 61f2189cc6..a95657be28 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 @@ -150,7 +150,7 @@ fun aUserEventPermissions( canRedactOther = canRedactOther, canSendMessage = canSendMessage, canSendReaction = canSendReaction, - canPin = canPin, + canPinUnpin = canPin, ) fun aReactionSummaryState( 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 c75054be3a..77a24b8c5d 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 @@ -25,5 +25,15 @@ data class UserEventPermissions( val canRedactOther: Boolean, val canSendMessage: Boolean, val canSendReaction: Boolean, - val canPin: Boolean, -) + val canPinUnpin: Boolean, +) { + companion object { + val DEFAULT = UserEventPermissions( + canRedactOwn = false, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + canPinUnpin = false + ) + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index 3387373734..55f58294f6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -133,8 +133,8 @@ private fun buildActions( add(TimelineItemAction.EndPoll) } // TODO: handle unpin - val canPin = isPinnedEventsEnabled && usersEventPermissions.canPin && timelineItem.isRemote - if (canPin) { + val canPinUnpin = isPinnedEventsEnabled && usersEventPermissions.canPinUnpin && timelineItem.isRemote + if (canPinUnpin) { add(TimelineItemAction.Pin) } if (timelineItem.content.canBeCopied()) { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index 17a051ba9b..e876b5ec60 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -53,7 +53,6 @@ import io.element.android.features.messages.impl.timeline.components.reactionsum import io.element.android.features.messages.impl.timeline.components.receipt.aReadReceiptData import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents import io.element.android.features.messages.impl.timeline.model.TimelineItem -import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.ui.strings.CommonStrings @@ -181,7 +180,7 @@ class MessagesViewTest { canRedactOwn = userHasPermissionToRedactOwn, canRedactOther = userHasPermissionToRedactOther, canSendReaction = userHasPermissionToSendReaction, - canPin = userCanPinEvent, + canPinUnpin = userCanPinEvent, ), ) val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/MatrixRoomPowerLevels.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/MatrixRoomPowerLevels.kt index ef4e6f747e..2abd42f519 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/MatrixRoomPowerLevels.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/MatrixRoomPowerLevels.kt @@ -65,3 +65,8 @@ suspend fun MatrixRoom.canRedactOwn(): Result = canUserRedactOwn(sessio * Shortcut for calling [MatrixRoom.canRedactOther] with our own user. */ suspend fun MatrixRoom.canRedactOther(): Result = canUserRedactOther(sessionId) + +/** + * Shortcut for calling [MatrixRoom.canUserPinUnpin] with our own user. + */ +suspend fun MatrixRoom.canPinUnpin(): Result = canUserPinUnpin(sessionId) 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 ab3c80a6e2..8ff8b1a894 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 @@ -56,6 +56,13 @@ fun MatrixRoom.canCall(updateKey: Long): State { } } +@Composable +fun MatrixRoom.canPinUnpin(updateKey: Long): State { + return produceState(initialValue = false, key1 = updateKey) { + value = canUserPinUnpin(sessionId).getOrElse { false } + } +} + @Composable fun MatrixRoom.isOwnUserAdmin(): Boolean { val roomInfo by roomInfoFlow.collectAsState(initial = null) From 6cf64b263e2a905e5bce40b071533d55c0f25073 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 29 Jul 2024 13:43:57 +0200 Subject: [PATCH 033/186] Pinned event : branch pinEvent action --- .../android/features/messages/impl/MessagesPresenter.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 c86b587063..12b7bf9f50 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 @@ -280,7 +280,14 @@ class MessagesPresenter @AssistedInject constructor( TimelineItemAction.Forward -> handleForwardAction(targetEvent) TimelineItemAction.ReportContent -> handleReportAction(targetEvent) TimelineItemAction.EndPoll -> handleEndPollAction(targetEvent, timelineState) - TimelineItemAction.Pin -> Timber.d("Pin action not implemented") + TimelineItemAction.Pin -> handlePinAction(targetEvent) + } + } + + private suspend fun handlePinAction(targetEvent: TimelineItem.Event) { + if (targetEvent.eventId == null) return + timelineController.invokeOnCurrentTimeline { + pinEvent(targetEvent.eventId) } } From 97cf00ec96bcee350bd3104b9df5329cfbc72028 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Jul 2024 11:52:45 +0200 Subject: [PATCH 034/186] Pinned events: add unpin action --- .../android/features/messages/impl/MessagesPresenter.kt | 8 ++++++++ .../messages/impl/actionlist/model/TimelineItemAction.kt | 2 ++ libraries/ui-strings/src/main/res/values/localazy.xml | 1 + 3 files changed, 11 insertions(+) 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 12b7bf9f50..3622208233 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 @@ -281,6 +281,7 @@ class MessagesPresenter @AssistedInject constructor( TimelineItemAction.ReportContent -> handleReportAction(targetEvent) TimelineItemAction.EndPoll -> handleEndPollAction(targetEvent, timelineState) TimelineItemAction.Pin -> handlePinAction(targetEvent) + TimelineItemAction.Unpin -> handleUnpinAction(targetEvent) } } @@ -291,6 +292,13 @@ class MessagesPresenter @AssistedInject constructor( } } + private suspend fun handleUnpinAction(targetEvent: TimelineItem.Event) { + if (targetEvent.eventId == null) return + timelineController.invokeOnCurrentTimeline { + unpinEvent(targetEvent.eventId) + } + } + private fun CoroutineScope.toggleReaction( emoji: String, eventId: EventId, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt index e8da131d8d..b9762c4056 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt @@ -40,4 +40,6 @@ sealed class TimelineItemAction( data object ReportContent : TimelineItemAction(CommonStrings.action_report_content, CompoundDrawables.ic_compound_chat_problem, destructive = true) data object EndPoll : TimelineItemAction(CommonStrings.action_end_poll, CompoundDrawables.ic_compound_polls_end) data object Pin : TimelineItemAction(CommonStrings.action_pin, CompoundDrawables.ic_compound_pin) + //TODO use the Unpin compound icon when available. + data object Unpin : TimelineItemAction(CommonStrings.action_unpin, CompoundDrawables.ic_compound_pin) } diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index c5d8f46622..a86f920ed9 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -110,6 +110,7 @@ "Take photo" "Tap for options" "Try again" + "Unpin" "View source" "Yes" "About" From 5e47c98699531710477fdef30ad5583892aa37f6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Jul 2024 13:32:10 +0200 Subject: [PATCH 035/186] Pinned events: branch pin/unpin according to current state --- .../impl/actionlist/ActionListPresenter.kt | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index 55f58294f6..664ebfe625 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -38,15 +38,21 @@ import io.element.android.features.messages.impl.timeline.model.event.canReact 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.EventId +import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import javax.inject.Inject class ActionListPresenter @Inject constructor( private val appPreferencesStore: AppPreferencesStore, private val featureFlagsService: FeatureFlagService, + private val room: MatrixRoom, ) : Presenter { @Composable override fun present(): ActionListState { @@ -58,6 +64,9 @@ class ActionListPresenter @Inject constructor( val isDeveloperModeEnabled by appPreferencesStore.isDeveloperModeEnabledFlow().collectAsState(initial = false) val isPinnedEventsEnabled by featureFlagsService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false) + val pinnedEventIds by remember { + room.roomInfoFlow.map { it.pinnedEventIds } + }.collectAsState(initial = persistentListOf()) fun handleEvents(event: ActionListEvents) { when (event) { @@ -67,6 +76,7 @@ class ActionListPresenter @Inject constructor( usersEventPermissions = event.userEventPermissions, isDeveloperModeEnabled = isDeveloperModeEnabled, isPinnedEventsEnabled = isPinnedEventsEnabled, + pinnedEventIds = pinnedEventIds, target = target, ) } @@ -83,6 +93,7 @@ class ActionListPresenter @Inject constructor( usersEventPermissions: UserEventPermissions, isDeveloperModeEnabled: Boolean, isPinnedEventsEnabled: Boolean, + pinnedEventIds: ImmutableList, target: MutableState ) = launch { target.value = ActionListState.Target.Loading(timelineItem) @@ -92,6 +103,7 @@ class ActionListPresenter @Inject constructor( usersEventPermissions = usersEventPermissions, isDeveloperModeEnabled = isDeveloperModeEnabled, isPinnedEventsEnabled = isPinnedEventsEnabled, + isEventPinned = pinnedEventIds.contains(timelineItem.eventId), ) val displayEmojiReactions = usersEventPermissions.canSendReaction && timelineItem.isRemote && @@ -113,6 +125,7 @@ private fun buildActions( usersEventPermissions: UserEventPermissions, isDeveloperModeEnabled: Boolean, isPinnedEventsEnabled: Boolean, + isEventPinned: Boolean, ): List { val canRedact = timelineItem.isMine && usersEventPermissions.canRedactOwn || !timelineItem.isMine && usersEventPermissions.canRedactOther return buildList { @@ -135,7 +148,11 @@ private fun buildActions( // TODO: handle unpin val canPinUnpin = isPinnedEventsEnabled && usersEventPermissions.canPinUnpin && timelineItem.isRemote if (canPinUnpin) { - add(TimelineItemAction.Pin) + if (isEventPinned) { + add(TimelineItemAction.Unpin) + } else { + add(TimelineItemAction.Pin) + } } if (timelineItem.content.canBeCopied()) { add(TimelineItemAction.Copy) From 66e06d7d1c86675d750fe8d34d3bdc39a6c5bc55 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Jul 2024 16:38:11 +0200 Subject: [PATCH 036/186] Pinned event : add some tests --- .../messages/impl/MessagesStateProvider.kt | 4 +- .../messages/impl/MessagesPresenterTest.kt | 73 +++++-- .../actionlist/ActionListPresenterTest.kt | 197 +++++++++++++++--- .../matrix/test/timeline/FakeTimeline.kt | 4 +- 4 files changed, 231 insertions(+), 47 deletions(-) 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 a95657be28..3f3a691a98 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 @@ -144,13 +144,13 @@ fun aUserEventPermissions( canRedactOther: Boolean = false, canSendMessage: Boolean = true, canSendReaction: Boolean = true, - canPin: Boolean = false, + canPinUnpin: Boolean = false, ) = UserEventPermissions( canRedactOwn = canRedactOwn, canRedactOther = canRedactOther, canSendMessage = canSendMessage, canSendReaction = canSendReaction, - canPinUnpin = canPin, + canPinUnpin = canPinUnpin, ) fun aReactionSummaryState( 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 74eccd00ca..2704e299c1 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 @@ -155,7 +155,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) assertThat(room.markAsReadCalls).isEmpty() val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -175,7 +177,9 @@ class MessagesPresenterTest { canRedactOwnResult = { Result.success(true) }, canRedactOtherResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ).apply { + canUserPinUnpinResult = { Result.success(true) }, + + ).apply { givenRoomInfo(aRoomInfo(hasRoomCall = true)) } val presenter = createMessagesPresenter(matrixRoom = room) @@ -203,7 +207,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -240,7 +246,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -298,7 +306,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) val presenter = createMessagesPresenter( clipboardHelper = clipboardHelper, matrixRoom = matrixRoom, @@ -487,7 +497,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(true) } liveTimeline.redactEventLambda = redactEventLambda @@ -561,7 +573,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -596,7 +610,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -620,7 +636,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -644,7 +662,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) room.givenRoomMembersState( MatrixRoomMembersState.Ready( persistentListOf( @@ -679,7 +699,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) room.givenRoomMembersState( MatrixRoomMembersState.Error( failure = Throwable(), @@ -715,7 +737,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) room.givenRoomMembersState(MatrixRoomMembersState.Unknown) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -741,7 +765,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) room.givenRoomMembersState( MatrixRoomMembersState.Ready( persistentListOf( @@ -781,7 +807,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -805,7 +833,9 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -826,7 +856,8 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(false) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -846,7 +877,8 @@ class MessagesPresenterTest { canRedactOwnResult = { Result.success(false) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, - ) + canUserPinUnpinResult = { Result.success(true) }, + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -892,6 +924,7 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, + canUserPinUnpinResult = { Result.success(true) }, ).apply { givenRoomInfo(aRoomInfo(id = roomId, name = "")) }, @@ -959,7 +992,11 @@ class MessagesPresenterTest { } } val featureFlagService = FakeFeatureFlagService() - val actionListPresenter = ActionListPresenter(appPreferencesStore = appPreferencesStore, featureFlagsService = featureFlagService) + val actionListPresenter = ActionListPresenter( + appPreferencesStore = appPreferencesStore, + featureFlagsService = featureFlagService, + room = matrixRoom, + ) val typingNotificationPresenter = TypingNotificationPresenter( room = matrixRoom, sessionPreferencesStore = sessionPreferencesStore, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt index 5bd16bfe61..e8ea7cbbc2 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt @@ -32,8 +32,13 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent import io.element.android.features.poll.api.pollcontent.aPollAnswerItemList +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_MESSAGE +import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.tests.testutils.WarmUpRule import kotlinx.collections.immutable.persistentListOf @@ -48,7 +53,7 @@ class ActionListPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -59,7 +64,7 @@ class ActionListPresenterTest { @Test fun `present - compute for message from me redacted`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -73,6 +78,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -95,7 +101,7 @@ class ActionListPresenterTest { @Test fun `present - compute for message from others redacted`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -113,6 +119,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -135,7 +142,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -153,6 +160,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -166,6 +174,7 @@ class ActionListPresenterTest { actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, + TimelineItemAction.Pin, TimelineItemAction.Copy, TimelineItemAction.CopyLink, TimelineItemAction.ViewSource, @@ -180,7 +189,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message cannot sent message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -197,7 +206,8 @@ class ActionListPresenterTest { canRedactOwn = true, canRedactOther = false, canSendMessage = false, - canSendReaction = true + canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -210,6 +220,7 @@ class ActionListPresenterTest { displayEmojiReactions = true, actions = persistentListOf( TimelineItemAction.Forward, + TimelineItemAction.Pin, TimelineItemAction.Copy, TimelineItemAction.CopyLink, TimelineItemAction.ViewSource, @@ -224,7 +235,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message and can redact`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -242,6 +253,7 @@ class ActionListPresenterTest { canRedactOther = true, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -253,6 +265,7 @@ class ActionListPresenterTest { actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, + TimelineItemAction.Pin, TimelineItemAction.Copy, TimelineItemAction.CopyLink, TimelineItemAction.ViewSource, @@ -268,7 +281,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message and cannot send reaction`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -285,7 +298,8 @@ class ActionListPresenterTest { canRedactOwn = false, canRedactOther = true, canSendMessage = true, - canSendReaction = false + canSendReaction = false, + canPinUnpin = true, ) ) ) @@ -297,6 +311,7 @@ class ActionListPresenterTest { actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, + TimelineItemAction.Pin, TimelineItemAction.Copy, TimelineItemAction.CopyLink, TimelineItemAction.ViewSource, @@ -312,7 +327,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -329,6 +344,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -343,6 +359,7 @@ class ActionListPresenterTest { TimelineItemAction.Reply, TimelineItemAction.Forward, TimelineItemAction.Edit, + TimelineItemAction.Pin, TimelineItemAction.Copy, TimelineItemAction.CopyLink, TimelineItemAction.ViewSource, @@ -357,7 +374,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message cannot redact`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -374,6 +391,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -388,6 +406,7 @@ class ActionListPresenterTest { TimelineItemAction.Reply, TimelineItemAction.Forward, TimelineItemAction.Edit, + TimelineItemAction.Pin, TimelineItemAction.Copy, TimelineItemAction.CopyLink, TimelineItemAction.ViewSource, @@ -401,7 +420,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a media item`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -419,6 +438,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ), ) ) @@ -432,6 +452,7 @@ class ActionListPresenterTest { actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, + TimelineItemAction.Pin, TimelineItemAction.CopyLink, TimelineItemAction.ViewSource, TimelineItemAction.Redact, @@ -445,7 +466,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a state item in debug build`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -462,6 +483,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -484,7 +506,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a state item in non-debuggable build`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -501,6 +523,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -512,7 +535,106 @@ class ActionListPresenterTest { @Test fun `present - compute message in non-debuggable build`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + val messageEvent = aMessageEvent( + isMine = true, + content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = null) + ) + initialState.eventSink.invoke( + ActionListEvents.ComputeForMessage( + event = messageEvent, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + canPinUnpin = true, + ) + ) + ) + // val loadingState = awaitItem() + // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) + val successState = awaitItem() + assertThat(successState.target).isEqualTo( + ActionListState.Target.Success( + event = messageEvent, + displayEmojiReactions = true, + actions = persistentListOf( + TimelineItemAction.Reply, + TimelineItemAction.Forward, + TimelineItemAction.Edit, + TimelineItemAction.Pin, + TimelineItemAction.Copy, + TimelineItemAction.CopyLink, + TimelineItemAction.Redact, + ) + ) + ) + initialState.eventSink.invoke(ActionListEvents.Clear) + assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) + } + } + + @Test + fun `present - compute message when user can't pin`() = runTest { + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + val messageEvent = aMessageEvent( + isMine = true, + content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = null) + ) + initialState.eventSink.invoke( + ActionListEvents.ComputeForMessage( + event = messageEvent, + userEventPermissions = aUserEventPermissions( + canRedactOwn = true, + canRedactOther = false, + canSendMessage = true, + canSendReaction = true, + canPinUnpin = false, + ) + ) + ) + // val loadingState = awaitItem() + // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) + val successState = awaitItem() + assertThat(successState.target).isEqualTo( + ActionListState.Target.Success( + event = messageEvent, + displayEmojiReactions = true, + actions = persistentListOf( + TimelineItemAction.Reply, + TimelineItemAction.Forward, + TimelineItemAction.Edit, + TimelineItemAction.Copy, + TimelineItemAction.CopyLink, + TimelineItemAction.ViewSource, + TimelineItemAction.Redact, + ) + ) + ) + initialState.eventSink.invoke(ActionListEvents.Clear) + assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) + } + } + + @Test + fun `present - compute message when event is already pinned`() = runTest { + val room = FakeMatrixRoom().apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) + } + val presenter = createActionListPresenter( + isDeveloperModeEnabled = true, + isPinFeatureEnabled = true, + room = room + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -529,6 +651,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -543,8 +666,10 @@ class ActionListPresenterTest { TimelineItemAction.Reply, TimelineItemAction.Forward, TimelineItemAction.Edit, + TimelineItemAction.Unpin, TimelineItemAction.Copy, TimelineItemAction.CopyLink, + TimelineItemAction.ViewSource, TimelineItemAction.Redact, ) ) @@ -556,7 +681,7 @@ class ActionListPresenterTest { @Test fun `present - compute message with no actions`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -578,6 +703,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -602,7 +728,7 @@ class ActionListPresenterTest { @Test fun `present - compute not sent message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -623,6 +749,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -643,7 +770,7 @@ class ActionListPresenterTest { @Test fun `present - compute for editable poll message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -661,6 +788,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -673,6 +801,7 @@ class ActionListPresenterTest { TimelineItemAction.Reply, TimelineItemAction.Edit, TimelineItemAction.EndPoll, + TimelineItemAction.Pin, TimelineItemAction.CopyLink, TimelineItemAction.Redact, ) @@ -683,7 +812,7 @@ class ActionListPresenterTest { @Test fun `present - compute for non-editable poll message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -701,6 +830,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true ) ) ) @@ -712,6 +842,7 @@ class ActionListPresenterTest { actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.EndPoll, + TimelineItemAction.Pin, TimelineItemAction.CopyLink, TimelineItemAction.Redact, ) @@ -722,7 +853,7 @@ class ActionListPresenterTest { @Test fun `present - compute for ended poll message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -740,6 +871,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true, ) ) ) @@ -750,6 +882,7 @@ class ActionListPresenterTest { displayEmojiReactions = true, actions = persistentListOf( TimelineItemAction.Reply, + TimelineItemAction.Pin, TimelineItemAction.CopyLink, TimelineItemAction.Redact, ) @@ -760,7 +893,7 @@ class ActionListPresenterTest { @Test fun `present - compute for voice message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -778,6 +911,7 @@ class ActionListPresenterTest { canRedactOther = false, canSendMessage = true, canSendReaction = true, + canPinUnpin = true ) ) ) @@ -789,6 +923,7 @@ class ActionListPresenterTest { actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, + TimelineItemAction.Pin, TimelineItemAction.CopyLink, TimelineItemAction.Redact, ) @@ -799,7 +934,7 @@ class ActionListPresenterTest { @Test fun `present - compute for call notify`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -833,8 +968,20 @@ class ActionListPresenterTest { } } -private fun createActionListPresenter(isDeveloperModeEnabled: Boolean): ActionListPresenter { +private fun createActionListPresenter( + isDeveloperModeEnabled: Boolean, + isPinFeatureEnabled: Boolean, + room: MatrixRoom = FakeMatrixRoom(), +): ActionListPresenter { val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled) - val featureFlagsService = FakeFeatureFlagService() - return ActionListPresenter(appPreferencesStore = preferencesStore, featureFlagsService = featureFlagsService) + val featureFlagsService = FakeFeatureFlagService( + initialState = mapOf( + FeatureFlags.PinnedEvents.key to isPinFeatureEnabled, + ) + ) + return ActionListPresenter( + appPreferencesStore = preferencesStore, + featureFlagsService = featureFlagsService, + room = room + ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt index 6216c7b182..b10edbad0f 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt @@ -372,12 +372,12 @@ class FakeTimeline( override suspend fun loadReplyDetails(eventId: EventId) = loadReplyDetailsLambda(eventId) - var pinEventLambda: (eventId: EventId) -> Result = lambdaError() + var pinEventLambda: (eventId: EventId) -> Result = { lambdaError()} override suspend fun pinEvent(eventId: EventId): Result { return pinEventLambda(eventId) } - var unpinEventLambda: (eventId: EventId) -> Result = lambdaError() + var unpinEventLambda: (eventId: EventId) -> Result = { lambdaError()} override suspend fun unpinEvent(eventId: EventId): Result { return unpinEventLambda(eventId) } From 46f5115c0a64818cfedd6ee38bc6f43c1393d351 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Jul 2024 16:40:18 +0200 Subject: [PATCH 037/186] Pinned events : clean up code --- .../impl/actionlist/ActionListPresenter.kt | 1 - .../impl/actionlist/model/TimelineItemAction.kt | 3 ++- .../messages/impl/timeline/model/TimelineItem.kt | 2 -- .../messages/impl/MessagesPresenterTest.kt | 15 --------------- .../libraries/matrix/api/timeline/Timeline.kt | 1 - .../matrix/test/timeline/FakeTimeline.kt | 4 ++-- 6 files changed, 4 insertions(+), 22 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index 664ebfe625..124f4e911d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -145,7 +145,6 @@ private fun buildActions( if (canRedact && timelineItem.content is TimelineItemPollContent && !timelineItem.content.isEnded) { add(TimelineItemAction.EndPoll) } - // TODO: handle unpin val canPinUnpin = isPinnedEventsEnabled && usersEventPermissions.canPinUnpin && timelineItem.isRemote if (canPinUnpin) { if (isEventPinned) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt index b9762c4056..a650dc88eb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt @@ -40,6 +40,7 @@ sealed class TimelineItemAction( data object ReportContent : TimelineItemAction(CommonStrings.action_report_content, CompoundDrawables.ic_compound_chat_problem, destructive = true) data object EndPoll : TimelineItemAction(CommonStrings.action_end_poll, CompoundDrawables.ic_compound_polls_end) data object Pin : TimelineItemAction(CommonStrings.action_pin, CompoundDrawables.ic_compound_pin) - //TODO use the Unpin compound icon when available. + + // TODO use the Unpin compound icon when available. data object Unpin : TimelineItemAction(CommonStrings.action_unpin, CompoundDrawables.ic_compound_pin) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt index 2ebb1bac24..5eea9851ae 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt @@ -18,7 +18,6 @@ package io.element.android.features.messages.impl.timeline.model import androidx.compose.runtime.Immutable import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemVirtualModel @@ -96,7 +95,6 @@ sealed interface TimelineItem { val isSticker: Boolean = content is TimelineItemStickerContent val isRemote = eventId != null - } @Immutable 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 2704e299c1..12b494508c 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 @@ -156,7 +156,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) assertThat(room.markAsReadCalls).isEmpty() val presenter = createMessagesPresenter(matrixRoom = room) @@ -178,7 +177,6 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ).apply { givenRoomInfo(aRoomInfo(hasRoomCall = true)) } @@ -208,7 +206,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { @@ -247,7 +244,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { @@ -307,7 +303,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) val presenter = createMessagesPresenter( clipboardHelper = clipboardHelper, @@ -498,7 +493,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(true) } @@ -574,7 +568,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -611,7 +604,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -637,7 +629,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -663,7 +654,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) room.givenRoomMembersState( MatrixRoomMembersState.Ready( @@ -700,7 +690,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) room.givenRoomMembersState( MatrixRoomMembersState.Error( @@ -738,7 +727,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) room.givenRoomMembersState(MatrixRoomMembersState.Unknown) val presenter = createMessagesPresenter(matrixRoom = room) @@ -766,7 +754,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) room.givenRoomMembersState( MatrixRoomMembersState.Ready( @@ -808,7 +795,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { @@ -834,7 +820,6 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt index eb2fbe9a30..f42ec5fbe9 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt @@ -187,5 +187,4 @@ interface Timeline : AutoCloseable { * pinned */ suspend fun unpinEvent(eventId: EventId): Result - } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt index b10edbad0f..ea9b353a67 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt @@ -372,12 +372,12 @@ class FakeTimeline( override suspend fun loadReplyDetails(eventId: EventId) = loadReplyDetailsLambda(eventId) - var pinEventLambda: (eventId: EventId) -> Result = { lambdaError()} + var pinEventLambda: (eventId: EventId) -> Result = { lambdaError() } override suspend fun pinEvent(eventId: EventId): Result { return pinEventLambda(eventId) } - var unpinEventLambda: (eventId: EventId) -> Result = { lambdaError()} + var unpinEventLambda: (eventId: EventId) -> Result = { lambdaError() } override suspend fun unpinEvent(eventId: EventId): Result { return unpinEventLambda(eventId) } From 2e7321c2eba49674e2c358a6053e9736b1dda9e2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Jul 2024 17:37:50 +0200 Subject: [PATCH 038/186] Sync on push : add featureflag --- .../android/libraries/featureflag/api/FeatureFlags.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 616a549e63..d279ae6976 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -120,4 +120,11 @@ enum class FeatureFlags( defaultValue = { it.buildType != BuildType.RELEASE }, isFinished = false, ), + SyncOnPush( + key = "feature.syncOnPush", + title = "Sync on push", + description = "Subscribe to room sync when a push is received", + defaultValue = { false }, + isFinished = false, + ), } From 08030b558af12cdfb7380ad9755b74321edfb566 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Jul 2024 17:38:51 +0200 Subject: [PATCH 039/186] Sync on push : call room.subscribeToSync when notifiable event is received --- libraries/push/impl/build.gradle.kts | 1 + .../push/impl/push/OnNotifiableEventReceived.kt | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/libraries/push/impl/build.gradle.kts b/libraries/push/impl/build.gradle.kts index 8970f1e3d0..02dacbde34 100644 --- a/libraries/push/impl/build.gradle.kts +++ b/libraries/push/impl/build.gradle.kts @@ -56,6 +56,7 @@ dependencies { implementation(projects.libraries.uiStrings) implementation(projects.libraries.troubleshoot.api) implementation(projects.features.call.api) + implementation(projects.libraries.featureflag.api) api(projects.libraries.pushproviders.api) api(projects.libraries.pushstore.api) api(projects.libraries.push.api) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/OnNotifiableEventReceived.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/OnNotifiableEventReceived.kt index cdcc6a1d93..eb6a6da8df 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/OnNotifiableEventReceived.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/OnNotifiableEventReceived.kt @@ -18,6 +18,9 @@ package io.element.android.libraries.push.impl.push import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.di.AppScope +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.push.impl.notifications.DefaultNotificationDrawerManager import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent import kotlinx.coroutines.CoroutineScope @@ -32,10 +35,23 @@ interface OnNotifiableEventReceived { class DefaultOnNotifiableEventReceived @Inject constructor( private val defaultNotificationDrawerManager: DefaultNotificationDrawerManager, private val coroutineScope: CoroutineScope, + private val matrixClientProvider: MatrixClientProvider, + private val featureFlagService: FeatureFlagService, ) : OnNotifiableEventReceived { override fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent) { coroutineScope.launch { + subscribeToRoomIfNeeded(notifiableEvent) defaultNotificationDrawerManager.onNotifiableEventReceived(notifiableEvent) } } + + private fun CoroutineScope.subscribeToRoomIfNeeded(notifiableEvent: NotifiableEvent) = launch { + if (!featureFlagService.isFeatureEnabled(FeatureFlags.SyncOnPush)) { + return@launch + } + val client = matrixClientProvider.getOrRestore(notifiableEvent.sessionId).getOrNull() ?: return@launch + client.getRoom(notifiableEvent.roomId)?.use { room -> + room.subscribeToSync() + } + } } From 38fb26e3c6f53e6546981ed4bd809ef1991dff4f Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Jul 2024 19:12:29 +0200 Subject: [PATCH 040/186] Pinned event : log and show snackbar on error --- .../android/features/messages/impl/MessagesPresenter.kt | 8 ++++++++ 1 file changed, 8 insertions(+) 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 3622208233..329196a958 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 @@ -289,6 +289,10 @@ class MessagesPresenter @AssistedInject constructor( if (targetEvent.eventId == null) return timelineController.invokeOnCurrentTimeline { pinEvent(targetEvent.eventId) + .onFailure { + Timber.e(it, "Failed to pin event ${targetEvent.eventId}") + snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_error)) + } } } @@ -296,6 +300,10 @@ class MessagesPresenter @AssistedInject constructor( if (targetEvent.eventId == null) return timelineController.invokeOnCurrentTimeline { unpinEvent(targetEvent.eventId) + .onFailure { + Timber.e(it, "Failed to unpin event ${targetEvent.eventId}") + snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_error)) + } } } From d5bc6828b9f16399fe33153a5a6734957c5f5617 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Jul 2024 19:13:35 +0200 Subject: [PATCH 041/186] Pinned events : add more tests on pin/unpin --- .../messages/impl/MessagesPresenterTest.kt | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) 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 12b494508c..52e62e65fa 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 @@ -43,6 +43,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.features.messages.impl.typing.TypingNotificationPresenter import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPlayer @@ -895,6 +896,62 @@ class MessagesPresenterTest { } } + @Test + fun `present - handle action pin`() = runTest { + val pinEventLambda = lambdaRecorder { _: EventId -> Result.success(true) } + val timeline = FakeTimeline().apply { + this.pinEventLambda = pinEventLambda + } + val room = FakeMatrixRoom( + liveTimeline = timeline, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + canUserPinUnpinResult = { Result.success(true) }, + ) + val presenter = createMessagesPresenter(matrixRoom = room) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val messageEvent = aMessageEvent( + content = aTimelineItemTextContent() + ) + val initialState = awaitFirstItem() + initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Pin, messageEvent)) + assert(pinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) + } + } + + @Test + fun `present - handle action unpin`() = runTest { + val unpinEventLambda = lambdaRecorder { _: EventId -> Result.success(true) } + val timeline = FakeTimeline().apply { + this.unpinEventLambda = unpinEventLambda + } + val room = FakeMatrixRoom( + liveTimeline = timeline, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + canUserPinUnpinResult = { Result.success(true) }, + ) + val presenter = createMessagesPresenter(matrixRoom = room) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val messageEvent = aMessageEvent( + content = aTimelineItemTextContent() + ) + val initialState = awaitFirstItem() + initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Unpin, messageEvent)) + assert(unpinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) + } + } + private suspend fun ReceiveTurbine.awaitFirstItem(): T { // Skip 2 item if Mentions feature is enabled, else 1 skipItems(if (FeatureFlags.Mentions.defaultValue(aBuildMeta())) 2 else 1) From 6743e3b52c2778ac6b30537200e17ff887a01b22 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Jul 2024 20:55:11 +0200 Subject: [PATCH 042/186] Pinned events : add more tests on pin/unpin --- .../messages/impl/MessagesPresenterTest.kt | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) 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 52e62e65fa..db85546e42 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 @@ -78,6 +78,7 @@ 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 import io.element.android.libraries.matrix.test.A_SESSION_ID_2 +import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser @@ -898,10 +899,9 @@ class MessagesPresenterTest { @Test fun `present - handle action pin`() = runTest { - val pinEventLambda = lambdaRecorder { _: EventId -> Result.success(true) } - val timeline = FakeTimeline().apply { - this.pinEventLambda = pinEventLambda - } + val successPinEventLambda = lambdaRecorder { _: EventId -> Result.success(true) } + val failurePinEventLambda = lambdaRecorder { _: EventId -> Result.failure(A_THROWABLE) } + val timeline = FakeTimeline() val room = FakeMatrixRoom( liveTimeline = timeline, canUserSendMessageResult = { _, _ -> Result.success(true) }, @@ -919,17 +919,23 @@ class MessagesPresenterTest { content = aTimelineItemTextContent() ) val initialState = awaitFirstItem() + + timeline.pinEventLambda = successPinEventLambda + initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Pin, messageEvent)) + assert(successPinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) + + timeline.pinEventLambda = failurePinEventLambda initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Pin, messageEvent)) - assert(pinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) + assert(failurePinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) + assertThat(awaitItem().snackbarMessage).isNotNull() } } @Test fun `present - handle action unpin`() = runTest { - val unpinEventLambda = lambdaRecorder { _: EventId -> Result.success(true) } - val timeline = FakeTimeline().apply { - this.unpinEventLambda = unpinEventLambda - } + val successUnpinEventLambda = lambdaRecorder { _: EventId -> Result.success(true) } + val failureUnpinEventLambda = lambdaRecorder { _: EventId -> Result.failure(A_THROWABLE) } + val timeline = FakeTimeline() val room = FakeMatrixRoom( liveTimeline = timeline, canUserSendMessageResult = { _, _ -> Result.success(true) }, @@ -947,8 +953,15 @@ class MessagesPresenterTest { content = aTimelineItemTextContent() ) val initialState = awaitFirstItem() + + timeline.unpinEventLambda = successUnpinEventLambda + initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Unpin, messageEvent)) + assert(successUnpinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) + + timeline.unpinEventLambda = failureUnpinEventLambda initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Unpin, messageEvent)) - assert(unpinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) + assert(failureUnpinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) + assertThat(awaitItem().snackbarMessage).isNotNull() } } From 6b8dba6bb2c0e3617fecff15f59847375882b50e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 11:08:11 +0200 Subject: [PATCH 043/186] Update dependency io.nlopez.compose.rules:detekt to v0.4.8 (#3254) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependency io.nlopez.compose.rules:detekt to v0.4.8 * Fix new lint issues --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- build.gradle.kts | 2 +- .../messages/impl/ExpandableBottomSheetScaffold.kt | 6 +++++- .../features/messages/impl/actionlist/ActionListView.kt | 1 + .../impl/timeline/components/TimelineItemEventRow.kt | 1 + .../timeline/components/TimelineItemReactionsLayout.kt | 2 +- .../messages/impl/typing/TypingNotificationView.kt | 1 + .../android/libraries/roomselect/impl/RoomSelectView.kt | 1 + .../troubleshoot/impl/TroubleshootNotificationsView.kt | 7 ++++--- 8 files changed, 15 insertions(+), 6 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8139ed6eb8..fe501b8f05 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -61,7 +61,7 @@ allprojects { config.from(files("$rootDir/tools/detekt/detekt.yml")) } dependencies { - detektPlugins("io.nlopez.compose.rules:detekt:0.4.5") + detektPlugins("io.nlopez.compose.rules:detekt:0.4.8") } // KtLint diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/ExpandableBottomSheetScaffold.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/ExpandableBottomSheetScaffold.kt index 3d61d43063..29bea5ca9e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/ExpandableBottomSheetScaffold.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/ExpandableBottomSheetScaffold.kt @@ -58,7 +58,11 @@ import kotlin.math.roundToInt * @param modifier The modifier for the layout. * @param sheetContentKey The key for the sheet content. If the key changes, the sheet will be remeasured. */ -@Suppress("ContentTrailingLambda") +@Suppress( + "ContentTrailingLambda", + // False positive + "MultipleEmitters", +) @OptIn(ExperimentalMaterial3Api::class) @Composable internal fun ExpandableBottomSheetScaffold( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt index ed6fffb90f..eb2cda8ca7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt @@ -218,6 +218,7 @@ private fun SheetContent( } } +@Suppress("MultipleEmitters") // False positive @Composable private fun MessageSummary(event: TimelineItem.Event, modifier: Modifier = Modifier) { val content: @Composable () -> Unit diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 528217d367..1116817ace 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -376,6 +376,7 @@ private fun MessageSenderInformation( } } +@Suppress("MultipleEmitters") // False positive @Composable private fun MessageEventBubbleContent( event: TimelineItem.Event, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsLayout.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsLayout.kt index b4ec1e7461..77e6c5b9ff 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsLayout.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsLayout.kt @@ -110,7 +110,7 @@ fun TimelineItemReactionsLayout( } val rows = rowsIn.toMutableList() val secondLastRow = rows[rows.size - 2].toMutableList() - val expandButtonPlaceable = secondLastRow.removeLast() + val expandButtonPlaceable = secondLastRow.removeAt(secondLastRow.lastIndex) lastRow.add(0, expandButtonPlaceable) rows[rows.size - 2] = secondLastRow rows[rows.size - 1] = lastRow diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationView.kt index c568635a02..4ab81677d3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationView.kt @@ -53,6 +53,7 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.room.RoomMember import kotlinx.collections.immutable.ImmutableList +@Suppress("MultipleEmitters") // False positive @Composable fun TypingNotificationView( state: TypingNotificationState, diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt index ba683438e6..ef2fea495e 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt @@ -64,6 +64,7 @@ import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toPersistentList +@Suppress("MultipleEmitters") // False positive @OptIn(ExperimentalMaterial3Api::class) @Composable fun RoomSelectView( diff --git a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsView.kt b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsView.kt index 26232f8d69..b48af4480f 100644 --- a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsView.kt +++ b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsView.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.troubleshoot.impl +import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.foundation.progressSemantics @@ -68,7 +69,7 @@ fun TroubleshootNotificationsView( } @Composable -private fun TroubleshootTestView( +private fun ColumnScope.TroubleshootTestView( testState: NotificationTroubleshootTestState, onQuickFixClick: () -> Unit, ) { @@ -127,7 +128,7 @@ private fun TroubleshootTestView( } @Composable -private fun TroubleshootNotificationsContent(state: TroubleshootNotificationsState) { +private fun ColumnScope.TroubleshootNotificationsContent(state: TroubleshootNotificationsState) { when (state.testSuiteState.mainState) { AsyncAction.Loading, AsyncAction.Confirming, @@ -197,7 +198,7 @@ private fun RunTestButton(state: TroubleshootNotificationsState) { } @Composable -private fun TestSuiteView( +private fun ColumnScope.TestSuiteView( testSuiteState: TroubleshootTestSuiteState, onQuickFixClick: (Int) -> Unit, ) { From 6e346e7d349b2c16fa045408519916998f3660bd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 11:13:01 +0000 Subject: [PATCH 044/186] Update dependency io.sentry:sentry-android to v7.13.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 d04849d390..3d72ff1786 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -187,7 +187,7 @@ play_services_oss_licenses = "com.google.android.gms:play-services-oss-licenses: # Analytics posthog = "com.posthog:posthog-android:3.4.2" -sentry = "io.sentry:sentry-android:7.12.1" +sentry = "io.sentry:sentry-android:7.13.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.23.1" From e96a11f5e553f0e2ea4a27a294190aa4a1376bc1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 31 Jul 2024 13:44:46 +0200 Subject: [PATCH 045/186] Pinned events : clean up banner code and add small test. --- .../messages/impl/MessagesPresenter.kt | 1 - .../banner/PinnedMessagesBannerPresenter.kt | 1 - .../PinnedMessagesBannerStateProvider.kt | 1 - .../pinned/banner/PinnedMessagesBannerView.kt | 8 +-- .../messages/impl/MessagesPresenterTest.kt | 35 +++++++------ .../PinnedMessagesBannerPresenterTest.kt | 50 +++++++++++++++++++ 6 files changed, 69 insertions(+), 27 deletions(-) create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt 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 6150cef84a..c17ac1035b 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 @@ -41,7 +41,6 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter import io.element.android.features.messages.impl.messagecomposer.MessageComposerState -import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerPresenter import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.timeline.TimelineEvents diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index fae2483359..e020581468 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -26,7 +26,6 @@ import io.element.android.libraries.architecture.Presenter import javax.inject.Inject class PinnedMessagesBannerPresenter @Inject constructor() : Presenter { - @Composable override fun present(): PinnedMessagesBannerState { var pinnedMessageCount by remember { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt index c4cce07f94..54fa0f12c0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt @@ -19,7 +19,6 @@ package io.element.android.features.messages.impl.pinned.banner import androidx.compose.ui.tooling.preview.PreviewParameterProvider internal class PinnedMessagesBannerStateProvider : PreviewParameterProvider { - override val values: Sequence get() = sequenceOf( aPinnedMessagesBannerState(pinnedMessagesCount = 1, currentPinnedMessageIndex = 0), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index dbae6a6133..99ca53fd69 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -32,15 +32,12 @@ import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawBehind @@ -138,7 +135,7 @@ private fun PinIndicators( val viewportSize = lazyListState.layoutInfo.viewportSize lazyListState.animateScrollToItem( pinIndex, - (indicatorHeight / 2 - viewportSize.height / 2) + indicatorHeight / 2 - viewportSize.height / 2 ) } LazyColumn( @@ -192,13 +189,12 @@ private fun PinnedMessageItem( overflow = TextOverflow.Ellipsis, maxLines = 1, ) - } } @PreviewsDayNight @Composable -fun PinnedMessagesBannerViewPreview(@PreviewParameter(PinnedMessagesBannerStateProvider::class) state: PinnedMessagesBannerState) = ElementPreview { +internal fun PinnedMessagesBannerViewPreview(@PreviewParameter(PinnedMessagesBannerStateProvider::class) state: PinnedMessagesBannerState) = ElementPreview { PinnedMessagesBannerView( state = state, ) 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 1fa345cc33..d04c0974e0 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 @@ -58,7 +58,6 @@ import io.element.android.features.poll.test.actions.FakeEndPollAction import io.element.android.features.poll.test.actions.FakeSendPollResponseAction import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -160,7 +159,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) assertThat(room.markAsReadCalls).isEmpty() val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -181,7 +180,7 @@ class MessagesPresenterTest { canRedactOtherResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ).apply { + ).apply { givenRoomInfo(aRoomInfo(hasRoomCall = true)) } val presenter = createMessagesPresenter(matrixRoom = room) @@ -210,7 +209,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -248,7 +247,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -307,7 +306,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val presenter = createMessagesPresenter( clipboardHelper = clipboardHelper, matrixRoom = matrixRoom, @@ -497,7 +496,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(true) } liveTimeline.redactEventLambda = redactEventLambda @@ -572,7 +571,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -608,7 +607,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -633,7 +632,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -658,7 +657,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) room.givenRoomMembersState( MatrixRoomMembersState.Ready( persistentListOf( @@ -694,7 +693,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) room.givenRoomMembersState( MatrixRoomMembersState.Error( failure = Throwable(), @@ -731,7 +730,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) room.givenRoomMembersState(MatrixRoomMembersState.Unknown) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -758,7 +757,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) room.givenRoomMembersState( MatrixRoomMembersState.Ready( persistentListOf( @@ -799,7 +798,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -824,7 +823,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -846,7 +845,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -867,7 +866,7 @@ class MessagesPresenterTest { canUserJoinCallResult = { Result.success(true) }, typingNoticeResult = { Result.success(Unit) }, canUserPinUnpinResult = { Result.success(true) }, - ) + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt new file mode 100644 index 0000000000..b57f40abbe --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.pinned.banner + +import com.google.common.truth.Truth.assertThat +import io.element.android.tests.testutils.test +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class PinnedMessagesBannerPresenterTest { + + @Test + fun `present - initial state`() = runTest { + val presenter = createPinnedMessagesBannerPresenter() + presenter.test { + val initialState = awaitItem() + assertThat(initialState.pinnedMessagesCount).isEqualTo(0) + assertThat(initialState.currentPinnedMessageIndex).isEqualTo(0) + } + } + + @Test + fun `present - move to next pinned message when there is no pinned events`() = runTest { + val presenter = createPinnedMessagesBannerPresenter() + presenter.test { + val initialState = awaitItem() + initialState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + // Nothing is emitted + ensureAllEventsConsumed() + } + } + + private fun createPinnedMessagesBannerPresenter(): PinnedMessagesBannerPresenter { + return PinnedMessagesBannerPresenter() + } +} From d2a9a2539eb29e8f5fe988f455c64d9e6019ca8f Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 31 Jul 2024 11:55:28 +0000 Subject: [PATCH 046/186] Update screenshots --- ...es.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png | 3 +++ ...es.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png | 3 +++ ...es.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png | 3 +++ ...es.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png | 3 +++ ...es.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png | 3 +++ ...es.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png | 3 +++ ....impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png | 3 +++ ....impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png | 3 +++ ....impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png | 3 +++ ....impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png | 3 +++ ....impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png | 3 +++ ....impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png | 3 +++ .../images/features.messages.impl_MessagesView_Day_13_en.png | 3 +++ .../images/features.messages.impl_MessagesView_Night_13_en.png | 3 +++ 14 files changed, 42 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_13_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_13_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png new file mode 100644 index 0000000000..f90fbae2ba --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9ec1466eb17ea18c5ac661edc4eac761324ec1a69b2425619ae0a10180a94f4 +size 9421 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png new file mode 100644 index 0000000000..711080fa41 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11327bd08f7abf227396c0e87ae3e9b12c359c4964af470f88de78900441d071 +size 12892 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png new file mode 100644 index 0000000000..37a8ad75bd --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c48c684c5f9fee3913d53ca4be05f241238407f5cc318d4e0e8c29ccbc2c9741 +size 12844 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png new file mode 100644 index 0000000000..2f641d946e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddfe2970e4d752d90bb2eca15def6c8ad4b90f7c1f63ba41fb72f0e62b823abc +size 12986 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png new file mode 100644 index 0000000000..497889d126 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ab99ab0cd33e5a6047da10abcc326461dd2c48054b25430558ff4038e86127c +size 13006 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png new file mode 100644 index 0000000000..b534bb1b97 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ba960c7ea314e6c7fc01bffce8420fd95f5be5d6413fb03013754d59e806ba8 +size 12928 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png new file mode 100644 index 0000000000..d18a4aa35d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3476e3eedc41388e72bcc24aafd03087d843a40d49bf6b7e3af4eb59646ba8f7 +size 9260 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png new file mode 100644 index 0000000000..12fbb5eea2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d63dfde90dbc97e3fc7d66065c2188bcb57d7b26cdfdbe91c49a0f46f1d6057 +size 12306 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png new file mode 100644 index 0000000000..651010cb68 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f89efc8e15ec358a6bdc599e887463276575fe542f4e4aa6ff3147164278f063 +size 12259 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png new file mode 100644 index 0000000000..c5806c5f65 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a559a833482b81c4b2a8a0476300d2ed24a38ff4d57605d0e3ad629fed744444 +size 12386 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png new file mode 100644 index 0000000000..336410e94a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdc34b90e105f771fd28b10abbcb482fa3fd338c4777d76718b300f3671253fd +size 12409 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png new file mode 100644 index 0000000000..29fe9fb14d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2cb2af60eadce7edc8c3e7824c92146f7effd60b70e8820428f42fa4c3ecc3d +size 12337 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_13_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_13_en.png new file mode 100644 index 0000000000..b1ba1bf25a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_13_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c002dd22d2d3658cd048ee33423c76f71bd7e716814b393bb09d0ef15a031c69 +size 59908 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_13_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_13_en.png new file mode 100644 index 0000000000..15cd6ed9ae --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_13_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff76271e211261e723285ee4dda84a50ac90f08df01d103db5284f62e43d6755 +size 59288 From 7279aa03c519e56cad401fbd786839a4c25a962d Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 31 Jul 2024 15:51:19 +0200 Subject: [PATCH 047/186] Pinned events : clean up more banner code --- .../impl/pinned/banner/PinnedMessagesBannerView.kt | 13 ++++++------- .../banner/PinnedMessagesBannerPresenterTest.kt | 1 - 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index 99ca53fd69..d6139f5aba 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -14,11 +14,8 @@ * limitations under the License. */ -@file:OptIn(ExperimentalFoundationApi::class) - package io.element.android.features.messages.impl.pinned.banner -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement.spacedBy @@ -44,6 +41,7 @@ import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -57,6 +55,7 @@ import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.pinnedMessageBannerBorder import io.element.android.libraries.designsystem.theme.pinnedMessageBannerIndicator import io.element.android.libraries.designsystem.utils.annotatedTextWithBold +import io.element.android.libraries.ui.strings.CommonStrings @Composable fun PinnedMessagesBannerView( @@ -110,7 +109,7 @@ fun PinnedMessagesBannerView( message = "This is a pinned message", modifier = Modifier.weight(1f) ) - TextButton(text = "View all", onClick = { /*TODO*/ }) + TextButton(text = stringResource(id = CommonStrings.screen_room_pinned_banner_view_all_button_title), onClick = { /*TODO*/ }) } } @@ -168,13 +167,13 @@ private fun PinnedMessageItem( message: String, modifier: Modifier = Modifier, ) { - val countMessage = "${index + 1} of $totalCount" - val fullMessage = "$countMessage Pinned messages" + val countMessage = stringResource(id = CommonStrings.screen_room_pinned_banner_indicator, index + 1, totalCount) + val fullCountMessage = stringResource(id = CommonStrings.screen_room_pinned_banner_indicator_description, countMessage) Column(modifier = modifier) { if (totalCount > 1) { Text( text = annotatedTextWithBold( - text = fullMessage, + text = fullCountMessage, boldText = countMessage, ), style = ElementTheme.typography.fontBodySmMedium, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index b57f40abbe..6cf1b8beb0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -22,7 +22,6 @@ import kotlinx.coroutines.test.runTest import org.junit.Test class PinnedMessagesBannerPresenterTest { - @Test fun `present - initial state`() = runTest { val presenter = createPinnedMessagesBannerPresenter() From 6ee86a2fc75b7e1a068e224600155e44c9f7eceb Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 31 Jul 2024 14:43:47 +0000 Subject: [PATCH 048/186] Update screenshots --- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_13_en.png | 4 ++-- .../features.messages.impl_MessagesView_Night_13_en.png | 4 ++-- 14 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png index f90fbae2ba..558c81c8b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9ec1466eb17ea18c5ac661edc4eac761324ec1a69b2425619ae0a10180a94f4 -size 9421 +oid sha256:7114202a1de9860547c525c0dadc110ce9e2e198465218ac2c33cf65f2f0eaa2 +size 9496 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png index 711080fa41..3d77277fec 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:11327bd08f7abf227396c0e87ae3e9b12c359c4964af470f88de78900441d071 -size 12892 +oid sha256:8e6b5fd9ecc2b01cc8a83f3fe8e34352de1792a82db85c396377a18246adad1a +size 12953 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png index 37a8ad75bd..cfd32bb09c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c48c684c5f9fee3913d53ca4be05f241238407f5cc318d4e0e8c29ccbc2c9741 -size 12844 +oid sha256:14ca5901134299e801e204e280d731e7de4072f1d522b076eb41c5f806897ed2 +size 12905 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png index 2f641d946e..40ed099f5b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddfe2970e4d752d90bb2eca15def6c8ad4b90f7c1f63ba41fb72f0e62b823abc -size 12986 +oid sha256:bb206284c642dd665290d5d553491e622b8e15a64df7bb2dbd91ea5d3a13e19a +size 13041 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png index 497889d126..15a58d4763 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ab99ab0cd33e5a6047da10abcc326461dd2c48054b25430558ff4038e86127c -size 13006 +oid sha256:a1940c4ee1e07c6a0198682460af1a6558fcaf14cb69ff061831cb591eb7aec3 +size 13066 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png index b534bb1b97..ac3fb40ad1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ba960c7ea314e6c7fc01bffce8420fd95f5be5d6413fb03013754d59e806ba8 -size 12928 +oid sha256:fee5c1dbcdf7929f4762b2915584fe45b7f39916a949663f03e8d7e85e991b4b +size 12988 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png index d18a4aa35d..625e940b9e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3476e3eedc41388e72bcc24aafd03087d843a40d49bf6b7e3af4eb59646ba8f7 -size 9260 +oid sha256:16658495b889654f152ba80a52111164f9682009b96abf1f3f20e660bd7c2407 +size 9297 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png index 12fbb5eea2..3de9e45d12 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d63dfde90dbc97e3fc7d66065c2188bcb57d7b26cdfdbe91c49a0f46f1d6057 -size 12306 +oid sha256:43651c4a7f10406f1a6a4b995467ba292d4a43bc198dcf352ae2e66694154de2 +size 12340 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png index 651010cb68..b320ff09e6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f89efc8e15ec358a6bdc599e887463276575fe542f4e4aa6ff3147164278f063 -size 12259 +oid sha256:cca8ebb1ec12497de7e2efc1725a2e4427eecd1d340ae8176d10f914def0af25 +size 12297 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png index c5806c5f65..8299ed3a1c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a559a833482b81c4b2a8a0476300d2ed24a38ff4d57605d0e3ad629fed744444 -size 12386 +oid sha256:37bf00fbf548b7ba3d601af1ca489e07e25059c2f5a68abf9b85f4c656cf482c +size 12425 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png index 336410e94a..533f421f11 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdc34b90e105f771fd28b10abbcb482fa3fd338c4777d76718b300f3671253fd -size 12409 +oid sha256:ed813a7003eb01a06667b10191990ed5bb3f75ee6a447cc4d52510b7e13b3724 +size 12448 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png index 29fe9fb14d..a3b1d03bce 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2cb2af60eadce7edc8c3e7824c92146f7effd60b70e8820428f42fa4c3ecc3d -size 12337 +oid sha256:6fa556ff7f6757c69c24e47520e08ccfd1b009d8e49a704c36d7fc4ca4186cbf +size 12378 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_13_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_13_en.png index b1ba1bf25a..c1200f26b4 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c002dd22d2d3658cd048ee33423c76f71bd7e716814b393bb09d0ef15a031c69 -size 59908 +oid sha256:35761e520dcd7ad01d3913a98479314a1df645bdf141214e3a180fe150d2e8fd +size 59959 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_13_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_13_en.png index 15cd6ed9ae..704ea5bb60 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff76271e211261e723285ee4dda84a50ac90f08df01d103db5284f62e43d6755 -size 59288 +oid sha256:acd2cf24e0a894936d6ed0896fb4ebcdba3529437e595ca54aa13a6f8ee79a5f +size 59327 From 97d4e639e5c841ca7ed782a0975fe2f64cdba892 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 31 Jul 2024 21:13:37 +0200 Subject: [PATCH 049/186] Sync on push : call startSync/stopSync --- .../impl/push/OnNotifiableEventReceived.kt | 18 +--- .../push/impl/push/SyncOnNotifiableEvent.kt | 87 +++++++++++++++++++ 2 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/SyncOnNotifiableEvent.kt diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/OnNotifiableEventReceived.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/OnNotifiableEventReceived.kt index eb6a6da8df..c7cd718925 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/OnNotifiableEventReceived.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/OnNotifiableEventReceived.kt @@ -18,9 +18,6 @@ package io.element.android.libraries.push.impl.push import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.di.AppScope -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.push.impl.notifications.DefaultNotificationDrawerManager import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent import kotlinx.coroutines.CoroutineScope @@ -35,23 +32,12 @@ interface OnNotifiableEventReceived { class DefaultOnNotifiableEventReceived @Inject constructor( private val defaultNotificationDrawerManager: DefaultNotificationDrawerManager, private val coroutineScope: CoroutineScope, - private val matrixClientProvider: MatrixClientProvider, - private val featureFlagService: FeatureFlagService, + private val syncOnNotifiableEvent: SyncOnNotifiableEvent, ) : OnNotifiableEventReceived { override fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent) { coroutineScope.launch { - subscribeToRoomIfNeeded(notifiableEvent) + launch { syncOnNotifiableEvent(notifiableEvent) } defaultNotificationDrawerManager.onNotifiableEventReceived(notifiableEvent) } } - - private fun CoroutineScope.subscribeToRoomIfNeeded(notifiableEvent: NotifiableEvent) = launch { - if (!featureFlagService.isFeatureEnabled(FeatureFlags.SyncOnPush)) { - return@launch - } - val client = matrixClientProvider.getOrRestore(notifiableEvent.sessionId).getOrNull() ?: return@launch - client.getRoom(notifiableEvent.roomId)?.use { room -> - room.subscribeToSync() - } - } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/SyncOnNotifiableEvent.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/SyncOnNotifiableEvent.kt new file mode 100644 index 0000000000..dd72e05ed8 --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/SyncOnNotifiableEvent.kt @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.push.impl.push + +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.matrix.api.MatrixClientProvider +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.sync.SyncService +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent +import io.element.android.services.appnavstate.api.AppForegroundStateService +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.withContext +import kotlinx.coroutines.withTimeoutOrNull +import java.util.concurrent.atomic.AtomicInteger +import javax.inject.Inject +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds + +class SyncOnNotifiableEvent @Inject constructor( + private val matrixClientProvider: MatrixClientProvider, + private val featureFlagService: FeatureFlagService, + private val appForegroundStateService: AppForegroundStateService, + private val dispatchers: CoroutineDispatchers, +) { + private var syncCounter = AtomicInteger(0) + + suspend operator fun invoke(notifiableEvent: NotifiableEvent) = withContext(dispatchers.io) { + if (!featureFlagService.isFeatureEnabled(FeatureFlags.SyncOnPush)) { + return@withContext + } + val client = matrixClientProvider.getOrRestore(notifiableEvent.sessionId).getOrNull() ?: return@withContext + client.getRoom(notifiableEvent.roomId)?.use { room -> + room.subscribeToSync() + + // If the app is in foreground, sync is already running, so just add the subscription. + if (!appForegroundStateService.isInForeground.value) { + val syncService = client.syncService() + syncService.startSyncIfNeeded() + room.waitsUntilEventIsKnown(eventId = notifiableEvent.eventId, timeout = 10.seconds) + syncService.stopSyncIfNeeded() + } + } + } + + private suspend fun MatrixRoom.waitsUntilEventIsKnown(eventId: EventId, timeout: Duration) { + withTimeoutOrNull(timeout) { + liveTimeline.timelineItems.first { timelineItems -> + timelineItems.any { timelineItem -> + when (timelineItem) { + is MatrixTimelineItem.Event -> timelineItem.eventId == eventId + else -> false + } + } + } + } + } + + private suspend fun SyncService.startSyncIfNeeded() { + if (syncCounter.getAndIncrement() == 0) { + startSync() + } + } + + private suspend fun SyncService.stopSyncIfNeeded() { + if (syncCounter.decrementAndGet() == 0 && !appForegroundStateService.isInForeground.value) { + stopSync() + } + } +} From 0b32dbebb5ec5b992aa448dfdbf6ab1b7f65b0fc Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 31 Jul 2024 21:14:29 +0200 Subject: [PATCH 050/186] tests : refactor some classes --- .../roomlist/impl/RoomListPresenterTest.kt | 5 +++-- .../libraries/matrix/test/room/FakeMatrixRoom.kt | 5 ++++- .../matrix/test/sync/FakeSyncService.kt | 16 +++++----------- libraries/push/impl/build.gradle.kts | 2 ++ .../impl/DefaultNavigationStateServiceTest.kt | 1 + .../test}/FakeAppForegroundStateService.kt | 2 +- 6 files changed, 16 insertions(+), 15 deletions(-) rename services/appnavstate/{impl/src/test/kotlin/io/element/android/services/appnavstate/impl => test/src/main/kotlin/io/element/android/services/appnavstate/test}/FakeAppForegroundStateService.kt (95%) diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt index 7a9a8b2744..4bf4510d2f 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt @@ -95,6 +95,7 @@ import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -219,7 +220,7 @@ class RoomListPresenterTest { val encryptionService = FakeEncryptionService().apply { emitRecoveryState(RecoveryState.INCOMPLETE) } - val syncService = FakeSyncService(initialState = SyncState.Running) + val syncService = FakeSyncService(MutableStateFlow(SyncState.Running)) val presenter = createRoomListPresenter( client = FakeMatrixClient(roomListService = roomListService, encryptionService = encryptionService, syncService = syncService), coroutineScope = scope, @@ -250,7 +251,7 @@ class RoomListPresenterTest { sessionVerificationService = FakeSessionVerificationService().apply { givenNeedsSessionVerification(false) }, - syncService = FakeSyncService(initialState = SyncState.Running) + syncService = FakeSyncService(MutableStateFlow(SyncState.Running)) ) val scope = CoroutineScope(context = coroutineContext + SupervisorJob()) val presenter = createRoomListPresenter( diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index e2be5bcb66..fef964c867 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -139,6 +139,7 @@ class FakeMatrixRoom( private val saveComposerDraftLambda: (ComposerDraft) -> Result = { _: ComposerDraft -> Result.success(Unit) }, private val loadComposerDraftLambda: () -> Result = { Result.success(null) }, private val clearComposerDraftLambda: () -> Result = { Result.success(Unit) }, + private val subscribeToSyncLambda: () -> Unit = { lambdaError() }, ) : MatrixRoom { private val _roomInfoFlow: MutableSharedFlow = MutableSharedFlow(replay = 1) override val roomInfoFlow: Flow = _roomInfoFlow @@ -181,7 +182,9 @@ class FakeMatrixRoom( timelineFocusedOnEventResult(eventId) } - override suspend fun subscribeToSync() = Unit + override suspend fun subscribeToSync() { + subscribeToSyncLambda() + } override suspend fun powerLevels(): Result { return powerLevelsResult() diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt index ffc06e7d18..32936d166e 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt @@ -22,22 +22,16 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow class FakeSyncService( - initialState: SyncState = SyncState.Idle + syncStateFlow: MutableStateFlow = MutableStateFlow(SyncState.Idle) ) : SyncService { - private val syncStateFlow = MutableStateFlow(initialState) - - fun simulateError() { - syncStateFlow.value = SyncState.Error - } - + var startSyncLambda: () -> Result = { Result.success(Unit) } override suspend fun startSync(): Result { - syncStateFlow.value = SyncState.Running - return Result.success(Unit) + return startSyncLambda() } + var stopSyncLambda: () -> Result = { Result.success(Unit) } override suspend fun stopSync(): Result { - syncStateFlow.value = SyncState.Terminated - return Result.success(Unit) + return stopSyncLambda() } override val syncState: StateFlow = syncStateFlow diff --git a/libraries/push/impl/build.gradle.kts b/libraries/push/impl/build.gradle.kts index 02dacbde34..f53b4ba27c 100644 --- a/libraries/push/impl/build.gradle.kts +++ b/libraries/push/impl/build.gradle.kts @@ -82,4 +82,6 @@ dependencies { testImplementation(projects.services.appnavstate.test) testImplementation(projects.services.toolbox.impl) testImplementation(projects.services.toolbox.test) + testImplementation(projects.libraries.featureflag.test) + testImplementation(libs.kotlinx.collections.immutable) } diff --git a/services/appnavstate/impl/src/test/kotlin/io/element/android/services/appnavstate/impl/DefaultNavigationStateServiceTest.kt b/services/appnavstate/impl/src/test/kotlin/io/element/android/services/appnavstate/impl/DefaultNavigationStateServiceTest.kt index 713839ee86..8f2abeeed5 100644 --- a/services/appnavstate/impl/src/test/kotlin/io/element/android/services/appnavstate/impl/DefaultNavigationStateServiceTest.kt +++ b/services/appnavstate/impl/src/test/kotlin/io/element/android/services/appnavstate/impl/DefaultNavigationStateServiceTest.kt @@ -31,6 +31,7 @@ import io.element.android.services.appnavstate.test.A_ROOM_OWNER import io.element.android.services.appnavstate.test.A_SESSION_OWNER import io.element.android.services.appnavstate.test.A_SPACE_OWNER import io.element.android.services.appnavstate.test.A_THREAD_OWNER +import io.element.android.services.appnavstate.test.FakeAppForegroundStateService import io.element.android.tests.testutils.runCancellableScopeTest import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.first diff --git a/services/appnavstate/impl/src/test/kotlin/io/element/android/services/appnavstate/impl/FakeAppForegroundStateService.kt b/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt similarity index 95% rename from services/appnavstate/impl/src/test/kotlin/io/element/android/services/appnavstate/impl/FakeAppForegroundStateService.kt rename to services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt index 4e3c012b48..6af17c78f3 100644 --- a/services/appnavstate/impl/src/test/kotlin/io/element/android/services/appnavstate/impl/FakeAppForegroundStateService.kt +++ b/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.services.appnavstate.impl +package io.element.android.services.appnavstate.test import io.element.android.services.appnavstate.api.AppForegroundStateService import kotlinx.coroutines.flow.MutableStateFlow From e1a1e4814e0973784671e2ecdd51235d775885d5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 31 Jul 2024 21:15:08 +0200 Subject: [PATCH 051/186] Sync on push : test SyncOnNotifiableEvent --- .../impl/push/SyncOnNotifiableEventTest.kt | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/SyncOnNotifiableEventTest.kt diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/SyncOnNotifiableEventTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/SyncOnNotifiableEventTest.kt new file mode 100644 index 0000000000..2e182e81ae --- /dev/null +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/SyncOnNotifiableEventTest.kt @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.push.impl.push + +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.sync.SyncState +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_UNIQUE_ID +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.FakeMatrixClientProvider +import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +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.anEventTimelineItem +import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent +import io.element.android.services.appnavstate.test.FakeAppForegroundStateService +import io.element.android.tests.testutils.lambda.assert +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class SyncOnNotifiableEventTest { + private val timelineItems = MutableStateFlow>(emptyList()) + private val syncStateFlow = MutableStateFlow(SyncState.Idle) + private val startSyncLambda = lambdaRecorder> { Result.success(Unit) } + private val stopSyncLambda = lambdaRecorder> { Result.success(Unit) } + private val subscribeToSyncLambda = lambdaRecorder { } + + private val liveTimeline = FakeTimeline( + timelineItems = timelineItems, + ) + private val room = FakeMatrixRoom( + roomId = A_ROOM_ID, + liveTimeline = liveTimeline, + subscribeToSyncLambda = subscribeToSyncLambda + ) + private val syncService = FakeSyncService(syncStateFlow).also { + it.startSyncLambda = startSyncLambda + it.stopSyncLambda = stopSyncLambda + } + + private val client = FakeMatrixClient( + syncService = syncService, + ).apply { + givenGetRoomResult(A_ROOM_ID, room) + } + + private val notifiableEvent = aNotifiableMessageEvent() + + @Test + fun `when feature flag is disabled, nothing happens`() = runTest { + val sut = createSyncOnNotifiableEvent(client = client, isSyncOnPushEnabled = false) + + sut(notifiableEvent) + + assert(startSyncLambda).isNeverCalled() + assert(stopSyncLambda).isNeverCalled() + assert(subscribeToSyncLambda).isNeverCalled() + } + + @Test + fun `when feature flag is enabled and app is in foreground, sync is not started`() = runTest { + val sut = createSyncOnNotifiableEvent(client = client, isAppInForeground = true, isSyncOnPushEnabled = true) + + sut(notifiableEvent) + + assert(startSyncLambda).isNeverCalled() + assert(stopSyncLambda).isNeverCalled() + assert(subscribeToSyncLambda).isCalledOnce() + } + + @Test + fun `when feature flag is enabled and app is in background, sync is started and stopped`() = runTest { + val sut = createSyncOnNotifiableEvent(client = client, isAppInForeground = false, isSyncOnPushEnabled = true) + + timelineItems.emit( + listOf(MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem())) + ) + syncStateFlow.emit(SyncState.Running) + sut(notifiableEvent) + + assert(startSyncLambda).isCalledOnce() + assert(stopSyncLambda).isCalledOnce() + assert(subscribeToSyncLambda).isCalledOnce() + } + + @Test + fun `when feature flag is enabled and app is in background, running multiple time only call once`() = runTest { + val sut = createSyncOnNotifiableEvent(client = client, isAppInForeground = false, isSyncOnPushEnabled = true) + + coroutineScope { + launch { sut(notifiableEvent) } + launch { sut(notifiableEvent) } + launch { + delay(1) + timelineItems.emit( + listOf(MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem())) + ) + } + } + + assert(startSyncLambda).isCalledOnce() + assert(stopSyncLambda).isCalledOnce() + assert(subscribeToSyncLambda).isCalledExactly(2) + } + + private fun TestScope.createSyncOnNotifiableEvent( + client: MatrixClient = FakeMatrixClient(), + isSyncOnPushEnabled: Boolean = true, + isAppInForeground: Boolean = true, + ): SyncOnNotifiableEvent { + val featureFlagService = FakeFeatureFlagService( + initialState = mapOf( + FeatureFlags.SyncOnPush.key to isSyncOnPushEnabled + ) + ) + val appForegroundStateService = FakeAppForegroundStateService( + initialValue = isAppInForeground + ) + val matrixClientProvider = FakeMatrixClientProvider { Result.success(client) } + return SyncOnNotifiableEvent( + matrixClientProvider = matrixClientProvider, + featureFlagService = featureFlagService, + appForegroundStateService = appForegroundStateService, + dispatchers = testCoroutineDispatchers(), + ) + } +} From d8532c0d19c1b5f59a7fe33f4aca81f6843b81b5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 1 Aug 2024 11:21:05 +0200 Subject: [PATCH 052/186] Sync on push : fix CallScreenPresenterTests after last changes. --- .../call/ui/CallScreenPresenterTest.kt | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt index 09e6c86158..f56163b25d 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt @@ -36,6 +36,7 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.FakeMatrixClientProvider import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.matrix.test.sync.FakeSyncService import io.element.android.libraries.matrix.test.widget.FakeMatrixWidgetDriver import io.element.android.libraries.network.useragent.UserAgentProvider import io.element.android.services.analytics.api.ScreenTracker @@ -43,11 +44,13 @@ import io.element.android.services.analytics.test.FakeScreenTracker import io.element.android.services.toolbox.api.systemclock.SystemClock import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilTimeout +import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.test.TestScope @@ -86,8 +89,9 @@ class CallScreenPresenterTest { @Test fun `present - with CallType RoomCall sets call as active, loads URL, runs WidgetDriver and notifies the other clients a call started`() = runTest { val sendCallNotificationIfNeededLambda = lambdaRecorder> { Result.success(Unit) } + val syncService = FakeSyncService(MutableStateFlow(SyncState.Running)) val fakeRoom = FakeMatrixRoom(sendCallNotificationIfNeededResult = sendCallNotificationIfNeededLambda) - val client = FakeMatrixClient().apply { + val client = FakeMatrixClient(syncService = syncService).apply { givenGetRoomResult(A_ROOM_ID, fakeRoom) } val widgetDriver = FakeMatrixWidgetDriver() @@ -216,7 +220,12 @@ class CallScreenPresenterTest { fun `present - automatically starts the Matrix client sync when on RoomCall`() = runTest { val navigator = FakeCallScreenNavigator() val widgetDriver = FakeMatrixWidgetDriver() - val matrixClient = FakeMatrixClient() + val syncStateFlow = MutableStateFlow(SyncState.Idle) + val startSyncLambda = lambdaRecorder> { Result.success(Unit) } + val syncService = FakeSyncService(syncStateFlow = syncStateFlow).apply { + this.startSyncLambda = startSyncLambda + } + val matrixClient = FakeMatrixClient(syncService = syncService) val presenter = createCallScreenPresenter( callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID), widgetDriver = widgetDriver, @@ -230,7 +239,7 @@ class CallScreenPresenterTest { }.test { consumeItemsUntilTimeout() - assertThat(matrixClient.syncService().syncState.value).isEqualTo(SyncState.Running) + assert(startSyncLambda).isCalledOnce() cancelAndIgnoreRemainingEvents() } @@ -240,7 +249,12 @@ class CallScreenPresenterTest { fun `present - automatically stops the Matrix client sync on dispose`() = runTest { val navigator = FakeCallScreenNavigator() val widgetDriver = FakeMatrixWidgetDriver() - val matrixClient = FakeMatrixClient() + val syncStateFlow = MutableStateFlow(SyncState.Running) + val stopSyncLambda = lambdaRecorder> { Result.success(Unit) } + val syncService = FakeSyncService(syncStateFlow = syncStateFlow).apply { + this.stopSyncLambda = stopSyncLambda + } + val matrixClient = FakeMatrixClient(syncService = syncService) val presenter = createCallScreenPresenter( callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID), widgetDriver = widgetDriver, @@ -262,7 +276,7 @@ class CallScreenPresenterTest { job.cancelAndJoin() - assertThat(matrixClient.syncService().syncState.value).isEqualTo(SyncState.Terminated) + assert(stopSyncLambda).isCalledOnce() } private fun TestScope.createCallScreenPresenter( From 039744c4be64e9c05dcd1ec6c90f1a42246b9ea4 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 1 Aug 2024 18:14:53 +0200 Subject: [PATCH 053/186] Pinned events : introduce banner formatter --- .../api/PinnedMessagesBannerFormatter.kt | 23 ++++ .../DefaultPinnedMessagesBannerFormatter.kt | 123 ++++++++++++++++++ .../impl/DefaultRoomLastMessageFormatter.kt | 17 +-- .../eventformatter/impl/PrefixWith.kt | 33 +++++ 4 files changed, 182 insertions(+), 14 deletions(-) create mode 100644 libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/PinnedMessagesBannerFormatter.kt create mode 100644 libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt create mode 100644 libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/PrefixWith.kt diff --git a/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/PinnedMessagesBannerFormatter.kt b/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/PinnedMessagesBannerFormatter.kt new file mode 100644 index 0000000000..9db3a19bd7 --- /dev/null +++ b/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/PinnedMessagesBannerFormatter.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.eventformatter.api + +import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem + +interface PinnedMessagesBannerFormatter { + fun format(event: EventTimelineItem): CharSequence +} diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt new file mode 100644 index 0000000000..91a6de9a95 --- /dev/null +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.eventformatter.impl + +import androidx.annotation.StringRes +import androidx.compose.ui.text.AnnotatedString +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.eventformatter.api.PinnedMessagesBannerFormatter +import io.element.android.libraries.matrix.api.permalink.PermalinkParser +import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.LocationMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent +import io.element.android.libraries.matrix.api.timeline.item.event.MessageType +import io.element.android.libraries.matrix.api.timeline.item.event.NoticeMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.OtherMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.PollContent +import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent +import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent +import io.element.android.libraries.matrix.api.timeline.item.event.StickerMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent +import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName +import io.element.android.libraries.matrix.ui.messages.toPlainText +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.services.toolbox.api.strings.StringProvider +import javax.inject.Inject + +@ContributesBinding(SessionScope::class) +class DefaultPinnedMessagesBannerFormatter @Inject constructor( + private val sp: StringProvider, + private val permalinkParser: PermalinkParser, +) : PinnedMessagesBannerFormatter { + + override fun format(event: EventTimelineItem): CharSequence { + return when (val content = event.content) { + is MessageContent -> processMessageContents(event, content) + is StickerContent -> { + content.body.prefixWith(CommonStrings.common_sticker) + } + is UnableToDecryptContent -> { + sp.getString(CommonStrings.common_waiting_for_decryption_key) + } + is PollContent -> { + content.question.prefixWith(CommonStrings.a11y_poll) + } + RedactedContent -> { + sp.getString(CommonStrings.common_message_removed) + } + else -> { + sp.getString(CommonStrings.common_unsupported_event) + } + } + } + + private fun processMessageContents( + event: EventTimelineItem, + messageContent: MessageContent, + ): CharSequence { + + return when (val messageType: MessageType = messageContent.type) { + is EmoteMessageType -> { + val senderDisambiguatedDisplayName = event.senderProfile.getDisambiguatedDisplayName(event.sender) + "* $senderDisambiguatedDisplayName ${messageType.body}" + } + is TextMessageType -> { + messageType.toPlainText(permalinkParser) + } + is VideoMessageType -> { + messageType.body.prefixWith(CommonStrings.common_video) + } + is ImageMessageType -> { + messageType.body.prefixWith(CommonStrings.common_image) + } + is StickerMessageType -> { + messageType.body.prefixWith(CommonStrings.common_sticker) + } + is LocationMessageType -> { + messageType.body.prefixWith(CommonStrings.common_shared_location) + } + is FileMessageType -> { + messageType.body.prefixWith(CommonStrings.common_file) + } + is AudioMessageType -> { + messageType.body.prefixWith(CommonStrings.common_audio) + } + is VoiceMessageType -> { + messageType.body.prefixWith(CommonStrings.common_voice_message) + } + is OtherMessageType -> { + messageType.body + } + is NoticeMessageType -> { + messageType.body + } + } + } + + private fun CharSequence.prefixWith(@StringRes res: Int): AnnotatedString { + val prefix = sp.getString(res) + return prefixWith(prefix) + } +} diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt index 13655c48f2..08a4045c43 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt @@ -79,7 +79,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor( RedactedContent -> { val message = sp.getString(CommonStrings.common_message_removed) if (!isDmRoom) { - prefix(message, senderDisambiguatedDisplayName) + message.prefixWith(senderDisambiguatedDisplayName) } else { message } @@ -90,7 +90,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor( is UnableToDecryptContent -> { val message = sp.getString(CommonStrings.common_waiting_for_decryption_key) if (!isDmRoom) { - prefix(message, senderDisambiguatedDisplayName) + message.prefixWith(senderDisambiguatedDisplayName) } else { message } @@ -113,7 +113,6 @@ class DefaultRoomLastMessageFormatter @Inject constructor( } is LegacyCallInviteContent -> sp.getString(CommonStrings.common_call_invite) is CallNotifyContent -> sp.getString(CommonStrings.common_call_started) - else -> null }?.take(MAX_SAFE_LENGTH) } @@ -168,16 +167,6 @@ class DefaultRoomLastMessageFormatter @Inject constructor( ): CharSequence = if (isDmRoom) { message } else { - prefix(message, senderDisambiguatedDisplayName) - } - - private fun prefix(message: String, senderDisambiguatedDisplayName: String): AnnotatedString { - return buildAnnotatedString { - withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { - append(senderDisambiguatedDisplayName) - } - append(": ") - append(message) - } + message.prefixWith(senderDisambiguatedDisplayName) } } diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/PrefixWith.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/PrefixWith.kt new file mode 100644 index 0000000000..a5991e31df --- /dev/null +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/PrefixWith.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.eventformatter.impl + +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle + +internal fun CharSequence.prefixWith(prefix: String): AnnotatedString { + return buildAnnotatedString { + withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { + append(prefix) + } + append(": ") + append(this@prefixWith) + } +} From 34fd21f4404ce4abea7ec1993efe1e8700dafdfa Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 1 Aug 2024 18:22:22 +0200 Subject: [PATCH 054/186] Pinned events : introduce pinnedEventsTimeline method. --- .../libraries/matrix/api/room/MatrixRoom.kt | 5 +++++ .../libraries/matrix/impl/room/RustMatrixRoom.kt | 15 +++++++++++++++ .../libraries/matrix/test/room/FakeMatrixRoom.kt | 5 +++++ 3 files changed, 25 insertions(+) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 76c9f902c7..a469904aac 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -106,6 +106,11 @@ interface MatrixRoom : Closeable { */ suspend fun timelineFocusedOnEvent(eventId: EventId): Result + /** + * Create a new timeline for the pinned events of the room. + */ + suspend fun pinnedEventsTimeline(): Result + fun destroy() suspend fun subscribeToSync() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 96beb99d5a..111370dcc4 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -192,6 +192,21 @@ class RustMatrixRoom( } } + override suspend fun pinnedEventsTimeline(): Result { + return runCatching { + innerRoom.pinnedEventsTimeline( + internalIdPrefix = "pinned_events", + maxEventsToLoad = 100u, + ).let { inner -> + createTimeline(inner, isLive = false) + } + }.onFailure { + if (it is CancellationException) { + throw it + } + } + } + override fun destroy() { roomCoroutineScope.cancel() liveTimeline.close() diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index e2be5bcb66..3904de05d3 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -135,6 +135,7 @@ class FakeMatrixRoom( private val updateMembersResult: () -> Unit = { lambdaError() }, private val getMembersResult: (Int) -> Result> = { lambdaError() }, private val timelineFocusedOnEventResult: (EventId) -> Result = { lambdaError() }, + private val pinnedEventsTimelineResult: () -> Result = { lambdaError() }, private val setSendQueueEnabledLambda: (Boolean) -> Unit = { _: Boolean -> }, private val saveComposerDraftLambda: (ComposerDraft) -> Result = { _: ComposerDraft -> Result.success(Unit) }, private val loadComposerDraftLambda: () -> Result = { Result.success(null) }, @@ -181,6 +182,10 @@ class FakeMatrixRoom( timelineFocusedOnEventResult(eventId) } + override suspend fun pinnedEventsTimeline(): Result = simulateLongTask { + pinnedEventsTimelineResult() + } + override suspend fun subscribeToSync() = Unit override suspend fun powerLevels(): Result { From f63b59e118ddf50c7857bb78bae6edd9ee4f2a0c Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 1 Aug 2024 18:34:52 +0200 Subject: [PATCH 055/186] Pinned events : start branching sdk data in the banner. --- features/messages/impl/build.gradle.kts | 1 + .../features/messages/impl/MessagesView.kt | 4 + .../messages/impl/di/MessagesModule.kt | 4 +- .../pinned/banner/PinnedMessagesBannerItem.kt | 25 +++++ .../banner/PinnedMessagesBannerPresenter.kt | 69 ++++++++++++- .../banner/PinnedMessagesBannerState.kt | 3 +- .../PinnedMessagesBannerStateProvider.kt | 8 ++ .../pinned/banner/PinnedMessagesBannerView.kt | 98 ++++++++++--------- .../PinnedMessagesBannerPresenterTest.kt | 17 +++- .../test/FakePinnedMessagesBannerFormatter.kt | 28 ++++++ 10 files changed, 201 insertions(+), 56 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerItem.kt create mode 100644 libraries/eventformatter/test/src/main/kotlin/io/element/android/libraries/eventformatter/test/FakePinnedMessagesBannerFormatter.kt diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index 781a42b2fb..c1d3067510 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -102,5 +102,6 @@ dependencies { testImplementation(projects.features.poll.test) testImplementation(projects.features.poll.impl) testImplementation(libs.androidx.compose.ui.test.junit) + testImplementation(projects.libraries.eventformatter.test) testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } 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 3f606f9fb9..962ed0f8ff 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 @@ -73,6 +73,7 @@ import io.element.android.features.messages.impl.messagecomposer.AttachmentsStat import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerView import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerView +import io.element.android.features.messages.impl.timeline.TimelineEvents import io.element.android.features.messages.impl.timeline.TimelineView import io.element.android.features.messages.impl.timeline.components.JoinCallMenuItem import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet @@ -401,6 +402,9 @@ private fun MessagesViewContent( ) { PinnedMessagesBannerView( state = state.pinnedMessagesBannerState, + onClick = { pinnedEventId -> + //state.timelineState.eventSink(TimelineEvents.FocusOnEvent(pinnedEventId)) + }, ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt index 77fafd0887..dba98edf3d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt @@ -22,9 +22,9 @@ import dagger.Module import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerPresenter import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.di.RoomScope -@ContributesTo(SessionScope::class) +@ContributesTo(RoomScope::class) @Module interface MessagesModule { @Binds diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerItem.kt new file mode 100644 index 0000000000..19dce8a4a0 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerItem.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.pinned.banner + +import androidx.compose.ui.text.AnnotatedString +import io.element.android.libraries.matrix.api.core.EventId + +data class PinnedMessagesBannerItem( + val eventId: EventId, + val formatted: AnnotatedString, +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index e020581468..d5968b6a7b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -17,28 +17,86 @@ package io.element.android.features.messages.impl.pinned.banner import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.ui.text.AnnotatedString import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.eventformatter.api.PinnedMessagesBannerFormatter +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onCompletion +import kotlinx.coroutines.flow.onEach import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds -class PinnedMessagesBannerPresenter @Inject constructor() : Presenter { +class PinnedMessagesBannerPresenter @Inject constructor( + private val room: MatrixRoom, + private val pinnedMessagesBannerFormatter: PinnedMessagesBannerFormatter, +) : Presenter { + + @OptIn(FlowPreview::class) @Composable override fun present(): PinnedMessagesBannerState { - var pinnedMessageCount by remember { - mutableIntStateOf(0) + var pinnedMessages by remember { + mutableStateOf>(emptyList()) } var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(0) } + LaunchedEffect(pinnedMessages) { + val pinnedMessageCount = pinnedMessages.size + if (currentPinnedMessageIndex >= pinnedMessageCount) { + currentPinnedMessageIndex = (pinnedMessageCount - 1).coerceAtLeast(0) + } + } + + LaunchedEffect(Unit) { + val pinnedEventsTimeline = room.pinnedEventsTimeline().getOrNull() ?: return@LaunchedEffect + pinnedEventsTimeline.timelineItems + .debounce(300.milliseconds) + .map { timelineItems -> + timelineItems.mapNotNull { timelineItem -> + when (timelineItem) { + is MatrixTimelineItem.Event -> { + val eventId = timelineItem.eventId ?: return@mapNotNull null + val formatted = pinnedMessagesBannerFormatter.format(timelineItem.event) + PinnedMessagesBannerItem( + eventId = eventId, + formatted = if (formatted is AnnotatedString) { + formatted + } else { + AnnotatedString(formatted.toString()) + }, + ) + } + else -> null + } + } + } + .flowOn(Dispatchers.Default) + .onEach { newPinnedMessages -> + pinnedMessages = newPinnedMessages + }.onCompletion { + pinnedEventsTimeline.close() + } + .launchIn(this) + } fun handleEvent(event: PinnedMessagesBannerEvents) { when (event) { is PinnedMessagesBannerEvents.MoveToNextPinned -> { - if (currentPinnedMessageIndex < pinnedMessageCount - 1) { + if (currentPinnedMessageIndex < pinnedMessages.size - 1) { currentPinnedMessageIndex++ } else { currentPinnedMessageIndex = 0 @@ -48,7 +106,8 @@ class PinnedMessagesBannerPresenter @Inject constructor() : Presenter Unit ) { - val displayBanner = pinnedMessagesCount > 0 && currentPinnedMessageIndex < pinnedMessagesCount + val displayBanner = pinnedMessagesCount > 0 && currentPinnedMessage != null } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt index 54fa0f12c0..dcd6a4984a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt @@ -16,7 +16,10 @@ package io.element.android.features.messages.impl.pinned.banner +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.matrix.api.core.EventId +import kotlin.random.Random internal class PinnedMessagesBannerStateProvider : PreviewParameterProvider { override val values: Sequence @@ -33,9 +36,14 @@ internal class PinnedMessagesBannerStateProvider : PreviewParameterProvider Unit = {} ) = PinnedMessagesBannerState( pinnedMessagesCount = pinnedMessagesCount, currentPinnedMessageIndex = currentPinnedMessageIndex, + currentPinnedMessage = currentPinnedMessage, eventSink = eventSink ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index d6139f5aba..7fe2fa49cd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -16,6 +16,7 @@ package io.element.android.features.messages.impl.pinned.banner +import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement.spacedBy @@ -32,8 +33,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -42,6 +41,7 @@ import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -55,39 +55,44 @@ import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.pinnedMessageBannerBorder import io.element.android.libraries.designsystem.theme.pinnedMessageBannerIndicator import io.element.android.libraries.designsystem.utils.annotatedTextWithBold +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.ui.strings.CommonStrings @Composable fun PinnedMessagesBannerView( state: PinnedMessagesBannerState, + onClick: (EventId) -> Unit, modifier: Modifier = Modifier, ) { + if (state.currentPinnedMessage == null) return + val borderColor = ElementTheme.colors.pinnedMessageBannerBorder Row( modifier = modifier - .background(color = ElementTheme.colors.bgCanvasDefault) - .fillMaxWidth() - .drawBehind { - val strokeWidth = 0.5.dp.toPx() - val y = size.height - strokeWidth / 2 - drawLine( - borderColor, - Offset(0f, y), - Offset(size.width, y), - strokeWidth - ) - drawLine( - borderColor, - Offset(0f, 0f), - Offset(size.width, 0f), - strokeWidth - ) - } - .shadow(elevation = 5.dp, spotColor = Color.Transparent) - .heightIn(min = 64.dp) - .clickable { - state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) - }, + .background(color = ElementTheme.colors.bgCanvasDefault) + .fillMaxWidth() + .drawBehind { + val strokeWidth = 0.5.dp.toPx() + val y = size.height - strokeWidth / 2 + drawLine( + borderColor, + Offset(0f, y), + Offset(size.width, y), + strokeWidth + ) + drawLine( + borderColor, + Offset(0f, 0f), + Offset(size.width, 0f), + strokeWidth + ) + } + .shadow(elevation = 5.dp, spotColor = Color.Transparent) + .heightIn(min = 64.dp) + .clickable { + onClick(state.currentPinnedMessage.eventId) + state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + }, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = spacedBy(10.dp) ) { @@ -106,7 +111,7 @@ fun PinnedMessagesBannerView( PinnedMessageItem( index = state.currentPinnedMessageIndex, totalCount = state.pinnedMessagesCount, - message = "This is a pinned message", + message = state.currentPinnedMessage.formatted, modifier = Modifier.weight(1f) ) TextButton(text = stringResource(id = CommonStrings.screen_room_pinned_banner_view_all_button_title), onClick = { /*TODO*/ }) @@ -119,14 +124,12 @@ private fun PinIndicators( pinsCount: Int, modifier: Modifier = Modifier, ) { - val indicatorHeight by remember { - derivedStateOf { - when (pinsCount) { - 0 -> 0 - 1 -> 32 - 2 -> 18 - else -> 11 - } + val indicatorHeight = remember(pinsCount) { + when (pinsCount) { + 0 -> 0 + 1 -> 32 + 2 -> 18 + else -> 11 } } val lazyListState = rememberLazyListState() @@ -141,20 +144,21 @@ private fun PinIndicators( modifier = modifier, state = lazyListState, verticalArrangement = spacedBy(2.dp), - userScrollEnabled = false + userScrollEnabled = false, + reverseLayout = true ) { items(pinsCount) { index -> Box( modifier = Modifier - .width(2.dp) - .height(indicatorHeight.dp) - .background( - color = if (index == pinIndex) { - ElementTheme.colors.iconAccentPrimary - } else { - ElementTheme.colors.pinnedMessageBannerIndicator - } - ) + .width(2.dp) + .height(indicatorHeight.dp) + .background( + color = if (index == pinIndex) { + ElementTheme.colors.iconAccentPrimary + } else { + ElementTheme.colors.pinnedMessageBannerIndicator + } + ) ) } } @@ -164,13 +168,13 @@ private fun PinIndicators( private fun PinnedMessageItem( index: Int, totalCount: Int, - message: String, + message: AnnotatedString, modifier: Modifier = Modifier, ) { val countMessage = stringResource(id = CommonStrings.screen_room_pinned_banner_indicator, index + 1, totalCount) val fullCountMessage = stringResource(id = CommonStrings.screen_room_pinned_banner_indicator_description, countMessage) Column(modifier = modifier) { - if (totalCount > 1) { + AnimatedVisibility (totalCount > 1) { Text( text = annotatedTextWithBold( text = fullCountMessage, @@ -179,6 +183,7 @@ private fun PinnedMessageItem( style = ElementTheme.typography.fontBodySmMedium, color = ElementTheme.colors.textActionAccent, maxLines = 1, + overflow = TextOverflow.Ellipsis, ) } Text( @@ -196,5 +201,6 @@ private fun PinnedMessageItem( internal fun PinnedMessagesBannerViewPreview(@PreviewParameter(PinnedMessagesBannerStateProvider::class) state: PinnedMessagesBannerState) = ElementPreview { PinnedMessagesBannerView( state = state, + onClick = {}, ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index 6cf1b8beb0..9ed181d9e1 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -17,6 +17,10 @@ package io.element.android.features.messages.impl.pinned.banner import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.eventformatter.api.PinnedMessagesBannerFormatter +import io.element.android.libraries.eventformatter.test.FakePinnedMessagesBannerFormatter +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest import org.junit.Test @@ -29,6 +33,7 @@ class PinnedMessagesBannerPresenterTest { val initialState = awaitItem() assertThat(initialState.pinnedMessagesCount).isEqualTo(0) assertThat(initialState.currentPinnedMessageIndex).isEqualTo(0) + assertThat(initialState.currentPinnedMessage).isNull() } } @@ -43,7 +48,15 @@ class PinnedMessagesBannerPresenterTest { } } - private fun createPinnedMessagesBannerPresenter(): PinnedMessagesBannerPresenter { - return PinnedMessagesBannerPresenter() + private fun createPinnedMessagesBannerPresenter( + room: MatrixRoom = FakeMatrixRoom(), + formatter: PinnedMessagesBannerFormatter = FakePinnedMessagesBannerFormatter( + formatLambda = { event -> "Content ${event.content}" } + ) + ): PinnedMessagesBannerPresenter { + return PinnedMessagesBannerPresenter( + room = room, + pinnedMessagesBannerFormatter = formatter + ) } } diff --git a/libraries/eventformatter/test/src/main/kotlin/io/element/android/libraries/eventformatter/test/FakePinnedMessagesBannerFormatter.kt b/libraries/eventformatter/test/src/main/kotlin/io/element/android/libraries/eventformatter/test/FakePinnedMessagesBannerFormatter.kt new file mode 100644 index 0000000000..668803169e --- /dev/null +++ b/libraries/eventformatter/test/src/main/kotlin/io/element/android/libraries/eventformatter/test/FakePinnedMessagesBannerFormatter.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.eventformatter.test + +import io.element.android.libraries.eventformatter.api.PinnedMessagesBannerFormatter +import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem + +class FakePinnedMessagesBannerFormatter( + val formatLambda: (event: EventTimelineItem) -> CharSequence +) : PinnedMessagesBannerFormatter { + override fun format(event: EventTimelineItem): CharSequence { + return formatLambda(event) + } +} From 8e8c271bc20db7926cbc8b880f2aee17092c0fc8 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 2 Aug 2024 11:14:24 +0200 Subject: [PATCH 056/186] Pinned events : only load data if feature is enabled --- .../banner/PinnedMessagesBannerItemFactory.kt | 47 ++++++++++ .../banner/PinnedMessagesBannerPresenter.kt | 91 ++++++++++--------- .../PinnedMessagesBannerPresenterTest.kt | 25 +++-- 3 files changed, 113 insertions(+), 50 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerItemFactory.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerItemFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerItemFactory.kt new file mode 100644 index 0000000000..95c13e1f64 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerItemFactory.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.pinned.banner + +import androidx.compose.ui.text.AnnotatedString +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.eventformatter.api.PinnedMessagesBannerFormatter +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import kotlinx.coroutines.withContext +import javax.inject.Inject + +class PinnedMessagesBannerItemFactory @Inject constructor( + private val coroutineDispatchers: CoroutineDispatchers, + private val formatter: PinnedMessagesBannerFormatter, +) { + suspend fun create(timelineItem: MatrixTimelineItem): PinnedMessagesBannerItem? = withContext(coroutineDispatchers.computation) { + when (timelineItem) { + is MatrixTimelineItem.Event -> { + val eventId = timelineItem.eventId ?: return@withContext null + val formatted = formatter.format(timelineItem.event) + PinnedMessagesBannerItem( + eventId = eventId, + formatted = if (formatted is AnnotatedString) { + formatted + } else { + AnnotatedString(formatted.toString()) + }, + ) + } + else -> null + } + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index d5968b6a7b..bc594ff49c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -18,21 +18,20 @@ package io.element.android.features.messages.impl.pinned.banner import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue -import androidx.compose.ui.text.AnnotatedString import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.eventformatter.api.PinnedMessagesBannerFormatter +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.room.MatrixRoom -import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion @@ -42,61 +41,37 @@ import kotlin.time.Duration.Companion.milliseconds class PinnedMessagesBannerPresenter @Inject constructor( private val room: MatrixRoom, - private val pinnedMessagesBannerFormatter: PinnedMessagesBannerFormatter, + private val itemFactory: PinnedMessagesBannerItemFactory, + private val featureFlagService: FeatureFlagService, ) : Presenter { - @OptIn(FlowPreview::class) @Composable override fun present(): PinnedMessagesBannerState { - var pinnedMessages by remember { + var pinnedItems by remember { mutableStateOf>(emptyList()) } + + fun onItemsChange(newItems: List) { + pinnedItems = newItems + } + var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(0) } - LaunchedEffect(pinnedMessages) { - val pinnedMessageCount = pinnedMessages.size + + LaunchedEffect(pinnedItems) { + val pinnedMessageCount = pinnedItems.size if (currentPinnedMessageIndex >= pinnedMessageCount) { currentPinnedMessageIndex = (pinnedMessageCount - 1).coerceAtLeast(0) } } - LaunchedEffect(Unit) { - val pinnedEventsTimeline = room.pinnedEventsTimeline().getOrNull() ?: return@LaunchedEffect - pinnedEventsTimeline.timelineItems - .debounce(300.milliseconds) - .map { timelineItems -> - timelineItems.mapNotNull { timelineItem -> - when (timelineItem) { - is MatrixTimelineItem.Event -> { - val eventId = timelineItem.eventId ?: return@mapNotNull null - val formatted = pinnedMessagesBannerFormatter.format(timelineItem.event) - PinnedMessagesBannerItem( - eventId = eventId, - formatted = if (formatted is AnnotatedString) { - formatted - } else { - AnnotatedString(formatted.toString()) - }, - ) - } - else -> null - } - } - } - .flowOn(Dispatchers.Default) - .onEach { newPinnedMessages -> - pinnedMessages = newPinnedMessages - }.onCompletion { - pinnedEventsTimeline.close() - } - .launchIn(this) - } + PinnedMessagesBannerItemsEffect(::onItemsChange) fun handleEvent(event: PinnedMessagesBannerEvents) { when (event) { is PinnedMessagesBannerEvents.MoveToNextPinned -> { - if (currentPinnedMessageIndex < pinnedMessages.size - 1) { + if (currentPinnedMessageIndex < pinnedItems.size - 1) { currentPinnedMessageIndex++ } else { currentPinnedMessageIndex = 0 @@ -106,10 +81,38 @@ class PinnedMessagesBannerPresenter @Inject constructor( } return PinnedMessagesBannerState( - pinnedMessagesCount = pinnedMessages.size, - currentPinnedMessage = pinnedMessages.getOrNull(currentPinnedMessageIndex), + pinnedMessagesCount = pinnedItems.size, + currentPinnedMessage = pinnedItems.getOrNull(currentPinnedMessageIndex), currentPinnedMessageIndex = currentPinnedMessageIndex, eventSink = ::handleEvent ) } + + @OptIn(FlowPreview::class) + @Composable + private fun PinnedMessagesBannerItemsEffect( + onItemsChange: (List) -> Unit, + ) { + val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false) + val updatedOnItemsChange by rememberUpdatedState(onItemsChange) + + LaunchedEffect(isFeatureEnabled) { + if (!isFeatureEnabled) return@LaunchedEffect + + val pinnedEventsTimeline = room.pinnedEventsTimeline().getOrNull() ?: return@LaunchedEffect + pinnedEventsTimeline.timelineItems + .debounce(300.milliseconds) + .map { timelineItems -> + timelineItems.mapNotNull { timelineItem -> + itemFactory.create(timelineItem) + } + } + .onEach { newItems -> + updatedOnItemsChange(newItems) + }.onCompletion { + pinnedEventsTimeline.close() + } + .launchIn(this) + } + } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index 9ed181d9e1..baab17577d 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -17,11 +17,14 @@ package io.element.android.features.messages.impl.pinned.banner import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.eventformatter.api.PinnedMessagesBannerFormatter import io.element.android.libraries.eventformatter.test.FakePinnedMessagesBannerFormatter +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.tests.testutils.test +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test @@ -48,15 +51,25 @@ class PinnedMessagesBannerPresenterTest { } } - private fun createPinnedMessagesBannerPresenter( + private fun TestScope.createPinnedMessagesBannerPresenter( room: MatrixRoom = FakeMatrixRoom(), - formatter: PinnedMessagesBannerFormatter = FakePinnedMessagesBannerFormatter( - formatLambda = { event -> "Content ${event.content}" } - ) + itemFactory: PinnedMessagesBannerItemFactory = PinnedMessagesBannerItemFactory( + coroutineDispatchers = testCoroutineDispatchers(), + formatter = FakePinnedMessagesBannerFormatter( + formatLambda = { event -> "Content ${event.content}" } + ) + ), + isFeatureEnabled: Boolean = true, ): PinnedMessagesBannerPresenter { + val featureFlagService = FakeFeatureFlagService( + initialState = mapOf( + FeatureFlags.PinnedEvents.key to isFeatureEnabled + ) + ) return PinnedMessagesBannerPresenter( room = room, - pinnedMessagesBannerFormatter = formatter + itemFactory = itemFactory, + featureFlagService = featureFlagService ) } } From 9d2e35db0d6df5cf4cc404637665fc16813508af Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 2 Aug 2024 12:18:36 +0200 Subject: [PATCH 057/186] Pinned events : add the glue for the ViewAll click. --- .../messages/impl/MessagesFlowNode.kt | 6 ++ .../features/messages/impl/MessagesNode.kt | 6 ++ .../features/messages/impl/MessagesView.kt | 10 ++- .../pinned/banner/PinnedMessagesBannerView.kt | 72 ++++++++++--------- .../typing/MessagesViewWithTypingPreview.kt | 3 +- .../messages/impl/MessagesViewTest.kt | 2 + 6 files changed, 60 insertions(+), 39 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index 4fd59be6cb..8523900981 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -17,6 +17,7 @@ package io.element.android.features.messages.impl import android.os.Parcelable +import android.widget.Toast import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier @@ -81,6 +82,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize +import timber.log.Timber @ContributesNode(RoomScope::class) class MessagesFlowNode @AssistedInject constructor( @@ -217,6 +219,10 @@ class MessagesFlowNode @AssistedInject constructor( analyticsService.captureInteraction(Interaction.Name.MobileRoomCallButton) elementCallEntryPoint.startCall(callType) } + + override fun onViewAllPinnedEvents() { + Timber.d("On View All Pinned Events not implemented yet.") + } } val inputs = MessagesNode.Inputs( focusedEventId = inputs.focusedEventId, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index b2ee1053a6..d722a5b7a0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -97,6 +97,7 @@ class MessagesNode @AssistedInject constructor( fun onCreatePollClick() fun onEditPollClick(eventId: EventId) fun onJoinCallClick(roomId: RoomId) + fun onViewAllPinnedEvents() } override fun onBuilt() { @@ -185,6 +186,10 @@ class MessagesNode @AssistedInject constructor( callbacks.forEach { it.onEditPollClick(eventId) } } + private fun onViewAllPinnedMessagesClick() { + callbacks.forEach { it.onViewAllPinnedEvents() } + } + private fun onSendLocationClick() { callbacks.forEach { it.onSendLocationClick() } } @@ -221,6 +226,7 @@ class MessagesNode @AssistedInject constructor( onSendLocationClick = this::onSendLocationClick, onCreatePollClick = this::onCreatePollClick, onJoinCallClick = this::onJoinCallClick, + onViewAllPinnedMessagesClick = this::onViewAllPinnedMessagesClick, modifier = modifier, ) 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 962ed0f8ff..17141d6496 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 @@ -73,7 +73,6 @@ import io.element.android.features.messages.impl.messagecomposer.AttachmentsStat import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerView import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerView -import io.element.android.features.messages.impl.timeline.TimelineEvents import io.element.android.features.messages.impl.timeline.TimelineView import io.element.android.features.messages.impl.timeline.components.JoinCallMenuItem import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet @@ -127,8 +126,9 @@ fun MessagesView( onSendLocationClick: () -> Unit, onCreatePollClick: () -> Unit, onJoinCallClick: () -> Unit, + onViewAllPinnedMessagesClick: () -> Unit, modifier: Modifier = Modifier, - forceJumpToBottomVisibility: Boolean = false + forceJumpToBottomVisibility: Boolean = false, ) { OnLifecycleEvent { _, event -> state.voiceMessageComposerState.eventSink(VoiceMessageComposerEvents.LifecycleEvent(event)) @@ -229,6 +229,7 @@ fun MessagesView( }, forceJumpToBottomVisibility = forceJumpToBottomVisibility, onJoinCallClick = onJoinCallClick, + onViewAllPinnedMessagesClick = onViewAllPinnedMessagesClick, ) }, snackbarHost = { @@ -320,6 +321,7 @@ private fun MessagesViewContent( onSendLocationClick: () -> Unit, onCreatePollClick: () -> Unit, onJoinCallClick: () -> Unit, + onViewAllPinnedMessagesClick: () -> Unit, forceJumpToBottomVisibility: Boolean, modifier: Modifier = Modifier, onSwipeToReply: (TimelineItem.Event) -> Unit, @@ -405,6 +407,7 @@ private fun MessagesViewContent( onClick = { pinnedEventId -> //state.timelineState.eventSink(TimelineEvents.FocusOnEvent(pinnedEventId)) }, + onViewAllClick = onViewAllPinnedMessagesClick, ) } } @@ -576,12 +579,13 @@ internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class) onBackClick = {}, onRoomDetailsClick = {}, onEventClick = { false }, - onPreviewAttachments = {}, onUserDataClick = {}, onLinkClick = {}, + onPreviewAttachments = {}, onSendLocationClick = {}, onCreatePollClick = {}, onJoinCallClick = {}, + onViewAllPinnedMessagesClick = { }, forceJumpToBottomVisibility = true, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index 7fe2fa49cd..9e7bec076d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -62,6 +62,7 @@ import io.element.android.libraries.ui.strings.CommonStrings fun PinnedMessagesBannerView( state: PinnedMessagesBannerState, onClick: (EventId) -> Unit, + onViewAllClick: () -> Unit, modifier: Modifier = Modifier, ) { if (state.currentPinnedMessage == null) return @@ -69,30 +70,30 @@ fun PinnedMessagesBannerView( val borderColor = ElementTheme.colors.pinnedMessageBannerBorder Row( modifier = modifier - .background(color = ElementTheme.colors.bgCanvasDefault) - .fillMaxWidth() - .drawBehind { - val strokeWidth = 0.5.dp.toPx() - val y = size.height - strokeWidth / 2 - drawLine( - borderColor, - Offset(0f, y), - Offset(size.width, y), - strokeWidth - ) - drawLine( - borderColor, - Offset(0f, 0f), - Offset(size.width, 0f), - strokeWidth - ) - } - .shadow(elevation = 5.dp, spotColor = Color.Transparent) - .heightIn(min = 64.dp) - .clickable { - onClick(state.currentPinnedMessage.eventId) - state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) - }, + .background(color = ElementTheme.colors.bgCanvasDefault) + .fillMaxWidth() + .drawBehind { + val strokeWidth = 0.5.dp.toPx() + val y = size.height - strokeWidth / 2 + drawLine( + borderColor, + Offset(0f, y), + Offset(size.width, y), + strokeWidth + ) + drawLine( + borderColor, + Offset(0f, 0f), + Offset(size.width, 0f), + strokeWidth + ) + } + .shadow(elevation = 5.dp, spotColor = Color.Transparent) + .heightIn(min = 64.dp) + .clickable { + onClick(state.currentPinnedMessage.eventId) + state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + }, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = spacedBy(10.dp) ) { @@ -114,7 +115,7 @@ fun PinnedMessagesBannerView( message = state.currentPinnedMessage.formatted, modifier = Modifier.weight(1f) ) - TextButton(text = stringResource(id = CommonStrings.screen_room_pinned_banner_view_all_button_title), onClick = { /*TODO*/ }) + TextButton(text = stringResource(id = CommonStrings.screen_room_pinned_banner_view_all_button_title), onClick = onViewAllClick) } } @@ -150,15 +151,15 @@ private fun PinIndicators( items(pinsCount) { index -> Box( modifier = Modifier - .width(2.dp) - .height(indicatorHeight.dp) - .background( - color = if (index == pinIndex) { - ElementTheme.colors.iconAccentPrimary - } else { - ElementTheme.colors.pinnedMessageBannerIndicator - } - ) + .width(2.dp) + .height(indicatorHeight.dp) + .background( + color = if (index == pinIndex) { + ElementTheme.colors.iconAccentPrimary + } else { + ElementTheme.colors.pinnedMessageBannerIndicator + } + ) ) } } @@ -174,7 +175,7 @@ private fun PinnedMessageItem( val countMessage = stringResource(id = CommonStrings.screen_room_pinned_banner_indicator, index + 1, totalCount) val fullCountMessage = stringResource(id = CommonStrings.screen_room_pinned_banner_indicator_description, countMessage) Column(modifier = modifier) { - AnimatedVisibility (totalCount > 1) { + AnimatedVisibility(totalCount > 1) { Text( text = annotatedTextWithBold( text = fullCountMessage, @@ -202,5 +203,6 @@ internal fun PinnedMessagesBannerViewPreview(@PreviewParameter(PinnedMessagesBan PinnedMessagesBannerView( state = state, onClick = {}, + onViewAllClick = {}, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/MessagesViewWithTypingPreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/MessagesViewWithTypingPreview.kt index c4a8a88153..9dadb7515d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/MessagesViewWithTypingPreview.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/MessagesViewWithTypingPreview.kt @@ -33,11 +33,12 @@ internal fun MessagesViewWithTypingPreview( onBackClick = {}, onRoomDetailsClick = {}, onEventClick = { false }, - onPreviewAttachments = {}, onUserDataClick = {}, onLinkClick = {}, + onPreviewAttachments = {}, onSendLocationClick = {}, onCreatePollClick = {}, onJoinCallClick = {}, + onViewAllPinnedMessagesClick = {}, ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index e876b5ec60..c88d2ffa28 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -471,6 +471,7 @@ private fun AndroidComposeTestRule.setMessa onSendLocationClick: () -> Unit = EnsureNeverCalled(), onCreatePollClick: () -> Unit = EnsureNeverCalled(), onJoinCallClick: () -> Unit = EnsureNeverCalled(), + onViewAllPinnedMessagesClick: () -> Unit = EnsureNeverCalled(), ) { setContent { // Cannot use the RichTextEditor, so simulate a LocalInspectionMode @@ -488,6 +489,7 @@ private fun AndroidComposeTestRule.setMessa onSendLocationClick = onSendLocationClick, onCreatePollClick = onCreatePollClick, onJoinCallClick = onJoinCallClick, + onViewAllPinnedMessagesClick = onViewAllPinnedMessagesClick, ) } } From ca47a1c6d5b980bc95d4ffaf1b3439cdb8fbe66f Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 2 Aug 2024 15:35:53 +0200 Subject: [PATCH 058/186] Pinned events : handle focus on pinned event --- .../messages/impl/MessagesFlowNode.kt | 1 - .../features/messages/impl/MessagesView.kt | 21 +++++---- .../banner/PinnedMessagesBannerPresenter.kt | 4 +- .../pinned/banner/PinnedMessagesBannerView.kt | 34 ++++++++++++++ .../messages/impl/timeline/TimelineEvents.kt | 3 +- .../impl/timeline/TimelinePresenter.kt | 45 +++++++++++-------- .../messages/impl/timeline/TimelineState.kt | 3 ++ .../messages/impl/timeline/TimelineView.kt | 10 ++++- .../impl/timeline/TimelinePresenterTest.kt | 13 ++++++ .../DefaultPinnedMessagesBannerFormatter.kt | 2 - .../impl/DefaultRoomLastMessageFormatter.kt | 5 --- 11 files changed, 101 insertions(+), 40 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index 8523900981..f022fd0caf 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -17,7 +17,6 @@ package io.element.android.features.messages.impl import android.os.Parcelable -import android.widget.Toast import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier 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 17141d6496..d983404f9b 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 @@ -36,7 +36,6 @@ import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme @@ -73,6 +72,8 @@ import io.element.android.features.messages.impl.messagecomposer.AttachmentsStat import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerView import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerView +import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerViewDefaults +import io.element.android.features.messages.impl.timeline.TimelineEvents import io.element.android.features.messages.impl.timeline.TimelineView import io.element.android.features.messages.impl.timeline.components.JoinCallMenuItem import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet @@ -105,14 +106,15 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.utils.KeepScreenOn import io.element.android.libraries.designsystem.utils.OnLifecycleEvent -import io.element.android.libraries.designsystem.utils.isScrollingUp import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import timber.log.Timber import kotlin.random.Random +import kotlin.time.Duration.Companion.milliseconds @Composable fun MessagesView( @@ -380,7 +382,7 @@ private fun MessagesViewContent( }, content = { paddingValues -> Box(modifier = Modifier.padding(paddingValues)) { - val timelineLazyListState = rememberLazyListState() + val scrollBehavior = PinnedMessagesBannerViewDefaults.rememberExitOnScrollBehavior() TimelineView( state = state.timelineState, typingNotificationState = state.typingNotificationState, @@ -395,18 +397,21 @@ private fun MessagesViewContent( onReadReceiptClick = onReadReceiptClick, forceJumpToBottomVisibility = forceJumpToBottomVisibility, onJoinCallClick = onJoinCallClick, - lazyListState = timelineLazyListState, + nestedScrollConnection = scrollBehavior.nestedScrollConnection, ) AnimatedVisibility( - visible = state.pinnedMessagesBannerState.displayBanner && timelineLazyListState.isScrollingUp(), + visible = state.pinnedMessagesBannerState.displayBanner && scrollBehavior.isVisible, enter = expandVertically(), exit = shrinkVertically(), ) { + fun focusOnPinnedEvent(eventId: EventId) { + state.timelineState.eventSink( + TimelineEvents.FocusOnEvent(eventId = eventId, debounce = 200.milliseconds) + ) + } PinnedMessagesBannerView( state = state.pinnedMessagesBannerState, - onClick = { pinnedEventId -> - //state.timelineState.eventSink(TimelineEvents.FocusOnEvent(pinnedEventId)) - }, + onClick = ::focusOnPinnedEvent, onViewAllClick = onViewAllPinnedMessagesClick, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index bc594ff49c..16b8c97af7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -44,7 +44,6 @@ class PinnedMessagesBannerPresenter @Inject constructor( private val itemFactory: PinnedMessagesBannerItemFactory, private val featureFlagService: FeatureFlagService, ) : Presenter { - @Composable override fun present(): PinnedMessagesBannerState { var pinnedItems by remember { @@ -109,7 +108,8 @@ class PinnedMessagesBannerPresenter @Inject constructor( } .onEach { newItems -> updatedOnItemsChange(newItems) - }.onCompletion { + } + .onCompletion { pinnedEventsTimeline.close() } .launchIn(this) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index 9e7bec076d..0ddbe1ed7b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -33,13 +33,19 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection +import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.style.TextOverflow @@ -197,6 +203,34 @@ private fun PinnedMessageItem( } } +@Stable +internal interface PinnedMessagesBannerViewScrollBehavior { + val isVisible: Boolean + val nestedScrollConnection: NestedScrollConnection +} + +internal object PinnedMessagesBannerViewDefaults { + @Composable + fun rememberExitOnScrollBehavior(): PinnedMessagesBannerViewScrollBehavior = remember { + ExitOnScrollBehavior() + } +} + +private class ExitOnScrollBehavior : PinnedMessagesBannerViewScrollBehavior { + override var isVisible by mutableStateOf(true) + override val nestedScrollConnection: NestedScrollConnection = object : NestedScrollConnection { + override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { + if (available.y < -1) { + isVisible = true + } + if (available.y > 1) { + isVisible = false + } + return Offset.Zero + } + } +} + @PreviewsDayNight @Composable internal fun PinnedMessagesBannerViewPreview(@PreviewParameter(PinnedMessagesBannerStateProvider::class) state: PinnedMessagesBannerState) = ElementPreview { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt index 24007530e6..25ed908cd0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt @@ -18,10 +18,11 @@ package io.element.android.features.messages.impl.timeline import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline +import kotlin.time.Duration sealed interface TimelineEvents { data class OnScrollFinished(val firstIndex: Int) : TimelineEvents - data class FocusOnEvent(val eventId: EventId) : TimelineEvents + data class FocusOnEvent(val eventId: EventId, val debounce: Duration = Duration.ZERO) : TimelineEvents data object ClearFocusRequestState : TimelineEvents data object OnFocusEventRender : TimelineEvents data object JumpToLive : TimelineEvents 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 f5903f036b..93667f3987 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 @@ -50,6 +50,7 @@ import io.element.android.libraries.matrix.ui.room.canSendMessageAsState import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -136,13 +137,8 @@ class TimelinePresenter @AssistedInject constructor( is TimelineEvents.EditPoll -> { navigator.onEditPollClick(event.pollStartId) } - is TimelineEvents.FocusOnEvent -> localScope.launch { - if (timelineItemIndexer.isKnown(event.eventId)) { - val index = timelineItemIndexer.indexOf(event.eventId) - focusRequestState.value = FocusRequestState.Success(eventId = event.eventId, index = index) - } else { - focusRequestState.value = FocusRequestState.Loading(eventId = event.eventId) - } + is TimelineEvents.FocusOnEvent -> { + focusRequestState.value = FocusRequestState.Requested(event.eventId, event.debounce) } is TimelineEvents.OnFocusEventRender -> { focusRequestState.value = focusRequestState.value.onFocusEventRender() @@ -157,18 +153,29 @@ class TimelinePresenter @AssistedInject constructor( } LaunchedEffect(focusRequestState.value) { - val currentFocusRequestState = focusRequestState.value - if (currentFocusRequestState is FocusRequestState.Loading) { - val eventId = currentFocusRequestState.eventId - timelineController.focusOnEvent(eventId) - .fold( - onSuccess = { - focusRequestState.value = FocusRequestState.Success(eventId = eventId) - }, - onFailure = { - focusRequestState.value = FocusRequestState.Failure(throwable = it) - } - ) + when (val currentFocusRequestState = focusRequestState.value) { + is FocusRequestState.Requested -> { + delay(currentFocusRequestState.debounce) + if (timelineItemIndexer.isKnown(currentFocusRequestState.eventId)) { + val index = timelineItemIndexer.indexOf(currentFocusRequestState.eventId) + focusRequestState.value = FocusRequestState.Success(eventId = currentFocusRequestState.eventId, index = index) + } else { + focusRequestState.value = FocusRequestState.Loading(eventId = currentFocusRequestState.eventId) + } + } + is FocusRequestState.Loading -> { + val eventId = currentFocusRequestState.eventId + timelineController.focusOnEvent(eventId) + .fold( + onSuccess = { + focusRequestState.value = FocusRequestState.Success(eventId = eventId) + }, + onFailure = { + focusRequestState.value = FocusRequestState.Failure(throwable = it) + } + ) + } + else -> Unit } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index eb8622d0bc..9339fcb620 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -21,6 +21,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.libraries.matrix.api.core.EventId import kotlinx.collections.immutable.ImmutableList +import kotlin.time.Duration @Immutable data class TimelineState( @@ -39,6 +40,7 @@ data class TimelineState( @Immutable sealed interface FocusRequestState { data object None : FocusRequestState + data class Requested(val eventId: EventId, val debounce: Duration) : FocusRequestState data class Loading(val eventId: EventId) : FocusRequestState data class Success( val eventId: EventId, @@ -54,6 +56,7 @@ sealed interface FocusRequestState { fun eventId(): EventId? { return when (this) { + is Requested -> eventId is Loading -> eventId is Success -> eventId else -> null diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index b640d9d450..2b62071c19 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -48,7 +48,10 @@ import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.rememberNestedScrollInteropConnection import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -91,7 +94,8 @@ fun TimelineView( onJoinCallClick: () -> Unit, modifier: Modifier = Modifier, lazyListState: LazyListState = rememberLazyListState(), - forceJumpToBottomVisibility: Boolean = false + forceJumpToBottomVisibility: Boolean = false, + nestedScrollConnection: NestedScrollConnection = rememberNestedScrollInteropConnection(), ) { fun clearFocusRequestState() { state.eventSink(TimelineEvents.ClearFocusRequestState) @@ -124,7 +128,9 @@ fun TimelineView( AnimatedVisibility(visible = true, enter = fadeIn()) { Box(modifier) { LazyColumn( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxSize() + .nestedScroll(nestedScrollConnection), state = lazyListState, reverseLayout = useReverseLayout, contentPadding = PaddingValues(vertical = 8.dp), 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 5a171227e7..90c71a964a 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 @@ -75,6 +75,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import java.util.Date +import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds private const val FAKE_UNIQUE_ID = "FAKE_UNIQUE_ID" @@ -496,6 +497,10 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" }.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) + awaitItem().also { state -> + assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) + assertThat(state.focusRequestState).isEqualTo(FocusRequestState.Requested(AN_EVENT_ID, Duration.ZERO)) + } awaitItem().also { state -> assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) assertThat(state.focusRequestState).isEqualTo(FocusRequestState.Loading(AN_EVENT_ID)) @@ -541,6 +546,10 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" }.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) + awaitItem().also { state -> + assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) + assertThat(state.focusRequestState).isEqualTo(FocusRequestState.Requested(AN_EVENT_ID, Duration.ZERO)) + } awaitItem().also { state -> assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) assertThat(state.focusRequestState).isEqualTo(FocusRequestState.Success(AN_EVENT_ID, 0)) @@ -564,6 +573,10 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" }.test { val initialState = awaitFirstItem() initialState.eventSink(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) + awaitItem().also { state -> + assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) + assertThat(state.focusRequestState).isEqualTo(FocusRequestState.Requested(AN_EVENT_ID, Duration.ZERO)) + } awaitItem().also { state -> assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) assertThat(state.focusRequestState).isEqualTo(FocusRequestState.Loading(AN_EVENT_ID)) diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt index 91a6de9a95..05403e5355 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt @@ -51,7 +51,6 @@ class DefaultPinnedMessagesBannerFormatter @Inject constructor( private val sp: StringProvider, private val permalinkParser: PermalinkParser, ) : PinnedMessagesBannerFormatter { - override fun format(event: EventTimelineItem): CharSequence { return when (val content = event.content) { is MessageContent -> processMessageContents(event, content) @@ -77,7 +76,6 @@ class DefaultPinnedMessagesBannerFormatter @Inject constructor( event: EventTimelineItem, messageContent: MessageContent, ): CharSequence { - return when (val messageType: MessageType = messageContent.type) { is EmoteMessageType -> { val senderDisambiguatedDisplayName = event.senderProfile.getDisambiguatedDisplayName(event.sender) diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt index 08a4045c43..ac125b48e6 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt @@ -16,11 +16,6 @@ package io.element.android.libraries.eventformatter.impl -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.withStyle import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.di.SessionScope import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter From b7c498a0a2cc6e474201028b558ffc08a64b35cc Mon Sep 17 00:00:00 2001 From: Guillaume <88834548+guillaumevillemont@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:18:09 +0200 Subject: [PATCH 059/186] Update sonarcloud project key (#3264) --- README.md | 6 +++--- build.gradle.kts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 35d4cffb27..25f2f2c835 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![Latest build](https://github.com/element-hq/element-x-android/actions/workflows/build.yml/badge.svg?query=branch%3Adevelop)](https://github.com/element-hq/element-x-android/actions/workflows/build.yml?query=branch%3Adevelop) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-x-android&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android) -[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-x-android&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android) -[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-x-android&metric=bugs)](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=element-x-android&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=element-x-android) +[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=element-x-android&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=element-x-android) +[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=element-x-android&metric=bugs)](https://sonarcloud.io/summary/new_code?id=element-x-android) [![codecov](https://codecov.io/github/element-hq/element-x-android/branch/develop/graph/badge.svg?token=ecwvia7amV)](https://codecov.io/github/vector-im/element-x-android) [![Element X Android Matrix room #element-x-android:matrix.org](https://img.shields.io/matrix/element-x-android:matrix.org.svg?label=%23element-x-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-x-android:matrix.org) [![Localazy](https://img.shields.io/endpoint?url=https%3A%2F%2Fconnect.localazy.com%2Fstatus%2Felement%2Fdata%3Fcontent%3Dall%26title%3Dlocalazy%26logo%3Dtrue)](https://localazy.com/p/element) diff --git a/build.gradle.kts b/build.gradle.kts index fe501b8f05..87771dae05 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -129,11 +129,11 @@ dependencyAnalysis { // To run a sonar analysis: // Run './gradlew sonar -Dsonar.login=' // The SONAR_LOGIN is stored in passbolt as Token Sonar Cloud Bma -// Sonar result can be found here: https://sonarcloud.io/project/overview?id=vector-im_element-x-android +// Sonar result can be found here: https://sonarcloud.io/project/overview?id=element-x-android sonar { properties { property("sonar.projectName", "element-x-android") - property("sonar.projectKey", "vector-im_element-x-android") + property("sonar.projectKey", "element-x-android") property("sonar.host.url", "https://sonarcloud.io") property("sonar.projectVersion", "1.0") // TODO project(":app").android.defaultConfig.versionName) property("sonar.sourceEncoding", "UTF-8") @@ -141,7 +141,7 @@ sonar { property("sonar.links.ci", "https://github.com/element-hq/element-x-android/actions") property("sonar.links.scm", "https://github.com/element-hq/element-x-android/") property("sonar.links.issue", "https://github.com/element-hq/element-x-android/issues") - property("sonar.organization", "new_vector_ltd_organization") + property("sonar.organization", "element-hq") property("sonar.login", if (project.hasProperty("SONAR_LOGIN")) project.property("SONAR_LOGIN")!! else "invalid") // exclude source code from analyses separated by a colon (:) From aca6f9e6654c5fc4efbd45490c8fb4e46627b9b7 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 2 Aug 2024 17:43:50 +0200 Subject: [PATCH 060/186] eventformatter : format m.room.pinned_events --- .../eventformatter/impl/StateContentFormatter.kt | 16 +++++++--------- .../impl/src/main/res/values/localazy.xml | 6 ++++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt index ef15216a66..164f54f911 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt @@ -80,6 +80,13 @@ class StateContentFormatter @Inject constructor( else -> sp.getString(R.string.state_event_room_topic_removed, senderDisambiguatedDisplayName) } } + OtherState.RoomPinnedEvents -> { + when { + //TODO manage all cases when available + senderIsYou -> sp.getString(R.string.state_event_room_pinned_events_changed_by_you) + else -> sp.getString(R.string.state_event_room_pinned_events_changed, senderDisambiguatedDisplayName) + } + } is OtherState.Custom -> when (renderingMode) { RenderingMode.RoomList -> { Timber.v("Filtering timeline item for room state change: $content") @@ -161,15 +168,6 @@ class StateContentFormatter @Inject constructor( "RoomJoinRules" } } - OtherState.RoomPinnedEvents -> when (renderingMode) { - RenderingMode.RoomList -> { - Timber.v("Filtering timeline item for room state change: $content") - null - } - RenderingMode.Timeline -> { - "RoomPinnedEvents" - } - } is OtherState.RoomUserPowerLevels -> when (renderingMode) { RenderingMode.RoomList -> { Timber.v("Filtering timeline item for room state change: $content") diff --git a/libraries/eventformatter/impl/src/main/res/values/localazy.xml b/libraries/eventformatter/impl/src/main/res/values/localazy.xml index 5e06d74e92..12dbc16a1d 100644 --- a/libraries/eventformatter/impl/src/main/res/values/localazy.xml +++ b/libraries/eventformatter/impl/src/main/res/values/localazy.xml @@ -45,6 +45,12 @@ "You removed the room name" "%1$s made no changes" "You made no changes" + "%1$s changed the pinned messages" + "You changed the pinned messages" + "%1$s pinned a message" + "You pinned a message" + "%1$s unpinned a message" + "You unpinned a message" "%1$s rejected the invitation" "You rejected the invitation" "%1$s removed %2$s" From dc9b79ee50da5bfedfcdaf0480b2cbed66b2463c Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 5 Aug 2024 08:11:27 +0100 Subject: [PATCH 061/186] Sync Strings (#3267) Co-authored-by: jmartinesp <480955+jmartinesp@users.noreply.github.com> --- .../src/main/res/values-be/translations.xml | 1 + .../src/main/res/values-cs/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 | 2 + .../src/main/res/values-et/translations.xml | 5 +- .../src/main/res/values-fr/translations.xml | 1 + .../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-pl/translations.xml | 1 + .../main/res/values-pt-rBR/translations.xml | 1 + .../src/main/res/values-pt/translations.xml | 3 + .../src/main/res/values-ro/translations.xml | 1 + .../src/main/res/values-ru/translations.xml | 3 + .../src/main/res/values-sk/translations.xml | 5 +- .../src/main/res/values-sv/translations.xml | 1 + .../main/res/values-zh-rTW/translations.xml | 1 + .../src/main/res/values-zh/translations.xml | 1 + .../impl/src/main/res/values/localazy.xml | 3 + .../src/main/res/values-be/translations.xml | 6 + .../src/main/res/values-et/translations.xml | 6 + .../src/main/res/values-pt/translations.xml | 6 + .../src/main/res/values-ru/translations.xml | 6 + .../src/main/res/values-sk/translations.xml | 6 + .../impl/src/main/res/values/localazy.xml | 6 + .../src/main/res/values-et/translations.xml | 13 + .../src/main/res/values-pt/translations.xml | 23 + .../src/main/res/values-ru/translations.xml | 13 + .../src/main/res/values-sk/translations.xml | 13 + .../src/main/res/values/localazy.xml | 13 + screenshots/html/data.js | 1129 +++++++++-------- 32 files changed, 712 insertions(+), 563 deletions(-) diff --git a/features/verifysession/impl/src/main/res/values-be/translations.xml b/features/verifysession/impl/src/main/res/values-be/translations.xml index 8b2c5e920d..5399805c90 100644 --- a/features/verifysession/impl/src/main/res/values-be/translations.xml +++ b/features/verifysession/impl/src/main/res/values-be/translations.xml @@ -3,6 +3,7 @@ "Стварыць новы ключ аднаўлення" "Пацвердзіце гэтую прыладу, каб наладзіць бяспечны абмен паведамленнямі." "Пацвердзіце, што гэта вы" + "Выкарыстоўвайце іншую прыладу" "Цяпер вы можаце бяспечна чытаць і адпраўляць паведамленні, і ўсе, з кім вы маеце зносіны ў чаце, таксама могуць давяраць гэтай прыладзе." "Прылада праверана" "Выкарыстоўвайце іншую прыладу" diff --git a/features/verifysession/impl/src/main/res/values-cs/translations.xml b/features/verifysession/impl/src/main/res/values-cs/translations.xml index fadcba869c..96d9aa0aa9 100644 --- a/features/verifysession/impl/src/main/res/values-cs/translations.xml +++ b/features/verifysession/impl/src/main/res/values-cs/translations.xml @@ -3,6 +3,7 @@ "Vytvoření nového klíče pro obnovení" "Ověřte toto zařízení a nastavte zabezpečené zasílání zpráv." "Potvrďte, že jste to vy" + "Použít jiné zařízení" "Nyní můžete bezpečně číst nebo odesílat zprávy, a kdokoli, s kým chatujete, může tomuto zařízení důvěřovat." "Zařízení ověřeno" "Použít jiné zařízení" diff --git a/features/verifysession/impl/src/main/res/values-de/translations.xml b/features/verifysession/impl/src/main/res/values-de/translations.xml index baad607403..a66479b3c1 100644 --- a/features/verifysession/impl/src/main/res/values-de/translations.xml +++ b/features/verifysession/impl/src/main/res/values-de/translations.xml @@ -3,6 +3,7 @@ "Erstelle einen neuen Wiederherstellungsschlüssel" "Verifiziere dieses Gerät, um sicheres Messaging einzurichten." "Bestätige, dass du es bist" + "Ein anderes Gerät verwenden" "Du kannst nun verschlüsselte Nachrichten lesen oder versenden." "Gerät verifiziert" "Ein anderes Gerät verwenden" diff --git a/features/verifysession/impl/src/main/res/values-el/translations.xml b/features/verifysession/impl/src/main/res/values-el/translations.xml index 5b0402cf50..93838717b7 100644 --- a/features/verifysession/impl/src/main/res/values-el/translations.xml +++ b/features/verifysession/impl/src/main/res/values-el/translations.xml @@ -3,6 +3,7 @@ "Δημιουργία νέου κλειδιού ανάκτησης" "Επαλήθευσε αυτήν τη συσκευή για να ρυθμίσεις την ασφαλή επικοινωνία." "Επιβεβαίωσε ότι είσαι εσύ" + "Χρήση άλλης συσκευής" "Τώρα μπορείς να διαβάζεις ή να στέλνεις μηνύματα με ασφάλεια και επίσης μπορεί να εμπιστευτεί αυτήν τη συσκευή οποιοσδήποτε με τον οποίο συνομιλείς." "Επαληθευμένη συσκευή" "Χρήση άλλης συσκευής" diff --git a/features/verifysession/impl/src/main/res/values-es/translations.xml b/features/verifysession/impl/src/main/res/values-es/translations.xml index b165818726..75773bd081 100644 --- a/features/verifysession/impl/src/main/res/values-es/translations.xml +++ b/features/verifysession/impl/src/main/res/values-es/translations.xml @@ -2,8 +2,10 @@ "Verifica este dispositivo para configurar la mensajería segura." "Confirma que eres tú" + "Usar otro dispositivo" "Ahora puedes leer o enviar mensajes de forma segura y cualquier persona con la que chatees también puede confiar en este dispositivo." "Dispositivo verificado" + "Usar otro dispositivo" "Algo no fue bien. Se agotó el tiempo de espera de la solicitud o se rechazó." "Confirma que los emojis que aparecen a continuación coinciden con los que aparecen en tu otra sesión." "Comparar emojis" diff --git a/features/verifysession/impl/src/main/res/values-et/translations.xml b/features/verifysession/impl/src/main/res/values-et/translations.xml index 219c7653e1..a9baa5bd9e 100644 --- a/features/verifysession/impl/src/main/res/values-et/translations.xml +++ b/features/verifysession/impl/src/main/res/values-et/translations.xml @@ -1,11 +1,14 @@ + "Kas kinnitamine pole võimalik?" "Loo uus taastevõti" "Krüptitud sõnumivahetuse tagamiseks verifitseeri see seade." "Kinnita, et see oled sina" + "Kasuta teist seadet" + "Kasuta taastevõtit" "Nüüd saad saata või lugeda sõnumeid turvaliselt ning kõik sinu vestluspartnerid võivad usaldada seda seadet." "Seade on verifitseeritud" - "Kasuta mõnda muud seadet" + "Kasuta teist seadet" "Ootame teise seadme järgi…" "Olukord pole päris õige. Päring kas aegus või teine osapool keeldus päringule vastamast." "Kinnita, et kõik järgnevalt kuvatud emojid on täpselt samad, mida sa näed oma teises sessioonis." diff --git a/features/verifysession/impl/src/main/res/values-fr/translations.xml b/features/verifysession/impl/src/main/res/values-fr/translations.xml index 6f7aa9982b..6750f48956 100644 --- a/features/verifysession/impl/src/main/res/values-fr/translations.xml +++ b/features/verifysession/impl/src/main/res/values-fr/translations.xml @@ -3,6 +3,7 @@ "Créer une nouvelle clé de récupération" "Vérifier cette session pour configurer votre messagerie sécurisée." "Confirmez votre identité" + "Utiliser une autre session" "Vous pouvez désormais lire ou envoyer des messages en toute sécurité, et toute personne avec qui vous discutez peut également faire confiance à cette session." "Session vérifiée" "Utiliser une autre session" diff --git a/features/verifysession/impl/src/main/res/values-hu/translations.xml b/features/verifysession/impl/src/main/res/values-hu/translations.xml index c31adb9736..34656caeae 100644 --- a/features/verifysession/impl/src/main/res/values-hu/translations.xml +++ b/features/verifysession/impl/src/main/res/values-hu/translations.xml @@ -3,6 +3,7 @@ "Új helyreállítási kulcs létrehozása" "A biztonságos üzenetkezelés beállításához ellenőrizze ezt az eszközt." "Erősítse meg, hogy Ön az" + "Másik eszköz használata" "Mostantól biztonságosan olvashat vagy küldhet üzeneteket, és bármelyik csevegőpartnere megbízhat ebben az eszközben." "Eszköz ellenőrizve" "Másik eszköz használata" diff --git a/features/verifysession/impl/src/main/res/values-in/translations.xml b/features/verifysession/impl/src/main/res/values-in/translations.xml index 3a3bec959e..50dc87d765 100644 --- a/features/verifysession/impl/src/main/res/values-in/translations.xml +++ b/features/verifysession/impl/src/main/res/values-in/translations.xml @@ -3,6 +3,7 @@ "Buat kunci pemulihan baru" "Verifikasi perangkat ini untuk menyiapkan perpesanan aman." "Konfirmasi bahwa ini Anda" + "Gunakan perangkat lain" "Sekarang Anda dapat membaca atau mengirim pesan dengan aman, dan siapa pun yang mengobrol dengan Anda juga dapat mempercayai perangkat ini." "Perangkat terverifikasi" "Gunakan perangkat lain" diff --git a/features/verifysession/impl/src/main/res/values-it/translations.xml b/features/verifysession/impl/src/main/res/values-it/translations.xml index 5e22712283..ac7036eebb 100644 --- a/features/verifysession/impl/src/main/res/values-it/translations.xml +++ b/features/verifysession/impl/src/main/res/values-it/translations.xml @@ -3,6 +3,7 @@ "Crea una nuova chiave di recupero" "Verifica questo dispositivo per segnare i tuoi messaggi come sicuri." "Conferma la tua identità" + "Usa un altro dispositivo" "Ora puoi leggere o inviare messaggi in tutta sicurezza e anche chi chatta con te può fidarsi di questo dispositivo." "Dispositivo verificato" "Usa un altro dispositivo" diff --git a/features/verifysession/impl/src/main/res/values-pl/translations.xml b/features/verifysession/impl/src/main/res/values-pl/translations.xml index 765d141669..07a3304ed9 100644 --- a/features/verifysession/impl/src/main/res/values-pl/translations.xml +++ b/features/verifysession/impl/src/main/res/values-pl/translations.xml @@ -3,6 +3,7 @@ "Utwórz nowy klucz przywracania" "Zweryfikuj to urządzenie, aby skonfigurować bezpieczne przesyłanie wiadomości." "Potwierdź, że to Ty" + "Użyj innego urządzenia" "Teraz możesz bezpiecznie czytać i wysyłać wiadomości, każdy z kim czatujesz również może ufać temu urządzeniu." "Urządzenie zweryfikowane" "Użyj innego urządzenia" diff --git a/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml b/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml index 3649a88f05..31da2e43d1 100644 --- a/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml @@ -1,5 +1,6 @@ + "Usar outro dispositivo" "Dispositivo verificado" "Usar outro dispositivo" "Algo não parece certo. Ou a solicitação atingiu o tempo limite ou a solicitação foi negada." diff --git a/features/verifysession/impl/src/main/res/values-pt/translations.xml b/features/verifysession/impl/src/main/res/values-pt/translations.xml index b563196913..a4d45ec9ef 100644 --- a/features/verifysession/impl/src/main/res/values-pt/translations.xml +++ b/features/verifysession/impl/src/main/res/values-pt/translations.xml @@ -1,8 +1,11 @@ + "Não é possível confirmar?" "Criar uma nova chave de recuperação" "Verifica este dispositivo para configurar o envio seguro de mensagens." "Confirma que és tu" + "Utilizar outro dispositivo" + "Utilizar chave de recuperação" "Agora podes ler ou enviar mensagens de forma segura, e qualquer pessoa com quem converses também pode confiar neste dispositivo." "Dispositivo verificado" "Utilizar outro dispositivo" diff --git a/features/verifysession/impl/src/main/res/values-ro/translations.xml b/features/verifysession/impl/src/main/res/values-ro/translations.xml index 91e837ddec..69bb6a20f5 100644 --- a/features/verifysession/impl/src/main/res/values-ro/translations.xml +++ b/features/verifysession/impl/src/main/res/values-ro/translations.xml @@ -3,6 +3,7 @@ "Creați o nouă cheie de recuperare" "Verificați acest dispozitiv pentru a configura mesagerie securizată." "Confirmați că sunteți dumneavoastră" + "Utilizați un alt dispozitiv" "Acum puteți citi sau trimite mesaje în siguranță, iar oricine cu care conversați poate avea încredere în acest dispozitiv." "Dispozitiv verificat" "Utilizați un alt dispozitiv" diff --git a/features/verifysession/impl/src/main/res/values-ru/translations.xml b/features/verifysession/impl/src/main/res/values-ru/translations.xml index c89077d172..fc685356d7 100644 --- a/features/verifysession/impl/src/main/res/values-ru/translations.xml +++ b/features/verifysession/impl/src/main/res/values-ru/translations.xml @@ -1,11 +1,14 @@ + "Не можете подтвердить?" "Создайте новый " "ключ восстановления" "Подтвердите это устройство, чтобы настроить безопасный обмен сообщениями." "Подтвердите, что это вы" + "Используйте другое устройство" + "Используйте recovery key" "Теперь вы можете безопасно читать и отправлять сообщения, и все, с кем вы общаетесь в чате, также могут доверять этому устройству." "Устройство проверено" "Используйте другое устройство" diff --git a/features/verifysession/impl/src/main/res/values-sk/translations.xml b/features/verifysession/impl/src/main/res/values-sk/translations.xml index b3089b7b30..a2ec2cb4b2 100644 --- a/features/verifysession/impl/src/main/res/values-sk/translations.xml +++ b/features/verifysession/impl/src/main/res/values-sk/translations.xml @@ -1,11 +1,14 @@ + "Nemôžete potvrdiť?" "Vytvoriť nový kľúč na obnovenie" "Ak chcete nastaviť zabezpečené správy, overte toto zariadenie." "Potvrďte, že ste to vy" + "Použite iné zariadenie" + "Použiť kľúč na obnovenie" "Teraz môžete bezpečne čítať alebo odosielať správy a tomuto zariadeniu môže dôverovať aj ktokoľvek, s kým konverzujete." "Zariadenie overené" - "Použiť iné zariadenie" + "Použite iné zariadenie" "Čaká sa na druhom zariadení…" "Zdá sa, že niečo nie je v poriadku. Časový limit žiadosti vypršal alebo bola žiadosť zamietnutá." "Skontrolujte, či sa emotikony uvedené nižšie zhodujú s emotikonmi zobrazenými vo vašej druhej relácii." diff --git a/features/verifysession/impl/src/main/res/values-sv/translations.xml b/features/verifysession/impl/src/main/res/values-sv/translations.xml index 392754174b..c65d66d0a4 100644 --- a/features/verifysession/impl/src/main/res/values-sv/translations.xml +++ b/features/verifysession/impl/src/main/res/values-sv/translations.xml @@ -3,6 +3,7 @@ "Skapa en ny återställningsnyckel" "Verifiera den här enheten för att konfigurera säkra meddelanden." "Bekräfta att det är du" + "Använd en annan enhet" "Nu kan du läsa eller skicka meddelanden säkert, och alla du chattar med kan också lita på den här enheten." "Enhet verifierad" "Använd en annan enhet" diff --git a/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml b/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml index f5a26eaf33..512e806c47 100644 --- a/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml @@ -3,6 +3,7 @@ "建立新的復原金鑰" "驗證這部裝置以設定安全通訊。" "確認這是你本人" + "使用另一部裝置" "您可以安全地讀取和發送訊息了,與您聊天的人也可以信任這部裝置。" "裝置已驗證" "使用另一部裝置" diff --git a/features/verifysession/impl/src/main/res/values-zh/translations.xml b/features/verifysession/impl/src/main/res/values-zh/translations.xml index 15cf93695f..b13b0e7686 100644 --- a/features/verifysession/impl/src/main/res/values-zh/translations.xml +++ b/features/verifysession/impl/src/main/res/values-zh/translations.xml @@ -3,6 +3,7 @@ "创建新的恢复密钥" "验证此设备以开始安全地收发消息。" "确认这是你" + "使用其他设备" "现在,您可以安全地阅读或发送消息,与您聊天的人也会信任此设备。" "设备已验证" "使用其他设备" diff --git a/features/verifysession/impl/src/main/res/values/localazy.xml b/features/verifysession/impl/src/main/res/values/localazy.xml index 41cd2f8dbc..45eda758a2 100644 --- a/features/verifysession/impl/src/main/res/values/localazy.xml +++ b/features/verifysession/impl/src/main/res/values/localazy.xml @@ -1,8 +1,11 @@ + "Can\'t confirm?" "Create a new recovery key" "Verify this device to set up secure messaging." "Confirm that it\'s you" + "Use another device" + "Use recovery key" "Now you can read or send messages securely, and anyone you chat with can also trust this device." "Device verified" "Use another device" diff --git a/libraries/eventformatter/impl/src/main/res/values-be/translations.xml b/libraries/eventformatter/impl/src/main/res/values-be/translations.xml index dcc942e4fc..5f1722ad1a 100644 --- a/libraries/eventformatter/impl/src/main/res/values-be/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-be/translations.xml @@ -45,6 +45,12 @@ "Вы выдалілі назву пакоя" "%1$s не зрабіў(-ла) ніякіх змен" "Вы не зрабілі ніякіх змен" + "%1$s змяніў(-ла) замацаваныя паведамленні" + "Вы змянілі замацаваныя паведамленні" + "%1$s замацаваў(-ла) паведамленне" + "Вы замацавалі паведамленне" + "%1$s адмацаваў(-ла) паведамленне" + "Вы адмацавалі паведамленне" "%1$s адхіліў(-ла) запрашэнне" "Вы адхілілі запрашэнне" "%1$s выдаліў(-ла) %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-et/translations.xml b/libraries/eventformatter/impl/src/main/res/values-et/translations.xml index 715453fbef..1d265d4004 100644 --- a/libraries/eventformatter/impl/src/main/res/values-et/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-et/translations.xml @@ -45,6 +45,12 @@ "Sina eemaldasid jututoa nime" "%1$s ei teinud ühtegi muudatust" "Sina ei teinud ühtegi muudatust" + "%1$s muutis klammerdatud sõnumeid" + "Sina muutsid klammerdatud sõnumeid" + "%1$s klammerdas sõnumi" + "Sina klammerdasid sõnumi" + "%1$s eemaldas klammerdatud sõnumi" + "Sina eemaldasid klammerdatud sõnumi" "%1$s lükkas kutse tagasi" "Sina lükkasid kutse tagasi" "%1$s eemaldas jututoast kasutaja %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-pt/translations.xml b/libraries/eventformatter/impl/src/main/res/values-pt/translations.xml index 6d214ab03e..9d21c1949c 100644 --- a/libraries/eventformatter/impl/src/main/res/values-pt/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-pt/translations.xml @@ -45,6 +45,12 @@ "Removeste o nome da sala" "%1$s não fiz nenhuma alteração" "Não fizeste nenhuma alteração" + "%1$s alterou as mensagens afixadas" + "Alteraste as mensagens afixadas" + "%1$s afixou uma mensagem" + "Afixaste uma mensagem" + "%1$s desafixou uma mensagem" + "Desafixaste uma mensagem" "%1$s rejeitou o convite" "Rejeitaste o convite" "%1$s removeu %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-ru/translations.xml b/libraries/eventformatter/impl/src/main/res/values-ru/translations.xml index a6a339bba6..385630ef4c 100644 --- a/libraries/eventformatter/impl/src/main/res/values-ru/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-ru/translations.xml @@ -45,6 +45,12 @@ "Вы удалили название комнаты" "%1$s ничего не изменил" "Вы не внесли никаких изменений" + "%1$s изменил закрепленные сообщения" + "Вы изменили закрепленные сообщения" + "%1$s закрепил сообщение" + "Вы закрепили сообщение" + "%1$s открепил сообщение" + "Вы открепили сообщение" "%1$s отклонил приглашение" "Вы отклонили приглашение" "%1$s удалил %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-sk/translations.xml b/libraries/eventformatter/impl/src/main/res/values-sk/translations.xml index 9a9f41a3fb..5e9976b80a 100644 --- a/libraries/eventformatter/impl/src/main/res/values-sk/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-sk/translations.xml @@ -45,6 +45,12 @@ "Odstránili ste názov miestnosti" "%1$s nevykonal/a žiadne zmeny" "Nevykonali ste žiadne zmeny" + "%1$s zmenil/a pripnuté správy" + "Zmenili ste pripnuté správy" + "%1$s pripol/la správu" + "Pripli ste správu" + "%1$s zrušil/a pripnutie správy" + "Zrušili ste pripnutie správy" "%1$s odmietol/a pozvánku" "Odmietli ste pozvánku" "%1$s odstránil/a %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values/localazy.xml b/libraries/eventformatter/impl/src/main/res/values/localazy.xml index 5e06d74e92..12dbc16a1d 100644 --- a/libraries/eventformatter/impl/src/main/res/values/localazy.xml +++ b/libraries/eventformatter/impl/src/main/res/values/localazy.xml @@ -45,6 +45,12 @@ "You removed the room name" "%1$s made no changes" "You made no changes" + "%1$s changed the pinned messages" + "You changed the pinned messages" + "%1$s pinned a message" + "You pinned a message" + "%1$s unpinned a message" + "You unpinned a message" "%1$s rejected the invitation" "You rejected the invitation" "%1$s removed %2$s" diff --git a/libraries/ui-strings/src/main/res/values-et/translations.xml b/libraries/ui-strings/src/main/res/values-et/translations.xml index a546b18f5d..c205c6910f 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -91,6 +91,7 @@ "Teata veast" "Teata sisust haldurile" "Lähtesta" + "Lähtesta on identiteet" "Proovi uuesti" "Proovi dekrüptimist uuesti" "Salvesta" @@ -266,9 +267,21 @@ Põhjus: %1$s." "Hei, suhtle minuga %1$s võrgus: %2$s" "%1$s Android" "Veast teatamiseks raputa nutiseadet ägedalt" + "Sinu kasutajakonto andmed, kontaktid, eelistused ja vestluste loend säiluvad" + "Sa kaotad seniste sõnumite ajaloo" + "Sa pead kõik oma olemasolevad seadmed ja kontaktid uuesti verifitseerima" + "Lähtesta oma identiteet vaid siis, kui sul pole ligipääsu mitte ühelegi oma seadmele ja sa oled kaotanud oma taastevõtme." + "Kui sa soovid jätkata selle rakenduse kasutamist ja sa pole mitte üheski seadmes sisse logitud ning oled kaotanud oma taastevõtme, siis tõesti pead lähtestama oma identiteedi. " + "Kui sa ühtegi muud võimalust ei leia, siis lähtesta oma identiteet." "Meediafaili valimine ei õnnestunud. Palun proovi uuesti." "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Meediafaili üleslaadimine ei õnnestunud. Palun proovi uuesti." + "Jah, lähtesta nüüd" + "See tegevus on tagasipöördumatu." + "Kas sa oled kindel, et soovid oma andmete krüptimist lähtestada?" + "Sisesta…" + "Palun kinnita, et soovid oma andmete krüptimist lähtestada." + "Jätkamaks sisesta oma kasutajakonto salasõna" "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Kasutaja andmete laadimine ei õnnestunud" "Blokeeri" 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 005082f743..630717a136 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -80,6 +80,7 @@ "OK" "Configurações" "Abrir com" + "Afixar" "Resposta rápida" "Citação" "Reagir" @@ -90,6 +91,7 @@ "Comunicar problema" "Denunciar conteúdo" "Repor" + "Repor identidade" "Tentar novamente" "Tentar decifragem novamente" "Guardar" @@ -109,6 +111,7 @@ "Tirar foto" "Toca para ver as opções" "Tentar novamente" + "Desafixar" "Ver fonte" "Sim" "Sobre" @@ -168,6 +171,7 @@ Razão: %1$s." "Sem resultados" "Sala sem nome" "Desligado" + "Licenças de código aberto" "ou" "Senha" "Pessoas" @@ -255,13 +259,29 @@ Razão: %1$s." "A %1$s não tem permissão para aceder ao teu microfone. Permite o acesso para gravar uma mensagem de voz." "Algumas mensagens não foram enviadas" "Ocorreu um erro, desculpa" + "A autenticidade desta mensagem cifrada não pode ser garantida neste dispositivo." + "Cifragem com origem num dispositivo eliminado ou desconhecido." + "Cifragem com origem num dispositivo não verificado pelo seu dono." + "Cifragem com origem num utilizador não verificado." "🔐️ Junta-te a mim na %1$s" "Alô! Fala comigo na %1$s: %2$s" "%1$s Android" "Agita o dispositivo em fúria para comunicar um problema" + "Os detalhes da tua conta, contactos, preferências e lista de conversas serão mantidos." + "Perderás o acesso ao teu histórico de mensagens existente" + "Necessitarás de verificar todos os teus dispositivos e contactos novamente." + "Repõe a tua identidade apenas se não tiveres acesso a mais nenhum dispositivo com sessão iniciada e se tiveres perdido a tua chave de recuperação." + "Se não tiveres sessão iniciada em nenhum outro dispositivo e perdeste o acesso à tua chave de recuperação, precisarás de repor a tua identidade para continuares a usar a aplicação. " + "Repõe a tua identidade caso não consigas confirmar de outra forma" "Falha ao selecionar multimédia, por favor tente novamente." "Falha ao processar multimédia para carregamento, por favor tente novamente." "Falhar ao carregar multimédia, por favor tente novamente." + "Sim, repor agora" + "Este processo é irreversível." + "Tens a certeza que pretendes repor a tua cifra?" + "Inserir…" + "Confirma que pretendes realmente repor a tua cifra." + "Insere a tua palavra-passe para continuares" "Falha ao processar multimédia para carregamento, por favor tente novamente." "Não foi possível obter os detalhes de utilizador." "Bloquear" @@ -271,6 +291,9 @@ Razão: %1$s." "Desbloquear" "Poderás voltar a ver todas as suas mensagens." "Desbloquear utilizador" + "%1$s de %2$s" + "%1$s mensagens afixadas" + "Ver todas" "Conversa" "Partilhar localização" "Partilhar a minha localização" 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 253479e53e..5f4815cc93 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -93,6 +93,7 @@ "Сообщить об ошибке" "Пожаловаться на содержание" "Сбросить" + "Сбросить идентификацию" "Повторить" "Повторите расшифровку" "Сохранить" @@ -272,9 +273,21 @@ "Привет, поговори со мной по %1$s: %2$s" "%1$s Android" "Встряхните устройство, чтобы сообщить об ошибке" + "Данные вашей учетной записи, контакты, настройки и список чатов будут сохранены" + "Вы потеряете существующую историю сообщений" + "Вам нужно будет заново подтвердить все существующие устройства и контакты." + "Сбрасывайте данные только в том случае, если у вас нет доступа к другому устройству, на котором выполнен вход, и вы потеряли ключ восстановления." + "Если вы не вошли в систему на других устройствах и потеряли ключ восстановления, вам необходимо сбросить учетные данные, чтобы продолжить использование приложения. " + "Сбросьте ключи подтверждения, если вы не можете подтвердить свою личность другим способом." "Не удалось выбрать носитель, попробуйте еще раз." "Не удалось обработать медиафайл для загрузки, попробуйте еще раз." "Не удалось загрузить медиафайлы, попробуйте еще раз." + "Да, сбросить сейчас" + "Этот процесс необратим." + "Вы действительно хотите сбросить шифрование?" + "Ввод…" + "Подтвердите, что вы хотите сбросить шифрование." + "Введите пароль своей учетной записи, чтобы продолжить" "Не удалось обработать медиафайл для загрузки, попробуйте еще раз." "Не удалось получить данные о пользователе" "Заблокировать" 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 00ad2f5a46..4de47203d2 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -93,6 +93,7 @@ "Nahlásiť chybu" "Nahlásiť obsah" "Obnoviť" + "Obnoviť identitu" "Skúsiť znova" "Opakovať dešifrovanie" "Uložiť" @@ -270,9 +271,21 @@ Dôvod: %1$s." "Ahoj, porozprávajte sa so mnou na %1$s: %2$s" "%1$s Android" "Zúrivo potriasť pre nahlásenie chyby" + "Údaje o vašom účte, kontakty, predvoľby a zoznam konverzácií budú zachované" + "Stratíte svoju existujúcu históriu správ" + "Budete musieť znova overiť všetky existujúce zariadenia a kontakty" + "Obnovte svoju totožnosť iba vtedy, ak nemáte prístup k inému prihlásenému zariadeniu a stratili ste kľúč na obnovenie." + "Ak nie ste prihlásení do žiadneho iného zariadenia a stratili ste kľúč na obnovenie, budete musieť znovu obnoviť svoju identitu, aby ste mohli pokračovať v používaní aplikácie. " + "Znovu nastavte svoju totožnosť v prípade, že ju nemôžete potvrdiť iným spôsobom" "Nepodarilo sa vybrať médium, skúste to prosím znova." "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa nahrať médiá, skúste to prosím znova." + "Áno, znovu nastaviť teraz" + "Tento proces je nezvratný." + "Naozaj chcete obnoviť svoje šifrovanie?" + "Zadajte…" + "Potvrďte, že chcete obnoviť svoje šifrovanie." + "Ak chcete pokračovať, zadajte heslo účtu" "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa získať údaje o používateľovi" "Zablokovať" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index a86f920ed9..5766c900dd 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -91,6 +91,7 @@ "Report bug" "Report content" "Reset" + "Reset identity" "Retry" "Retry decryption" "Save" @@ -266,9 +267,21 @@ Reason: %1$s." "Hey, talk to me on %1$s: %2$s" "%1$s Android" "Rageshake to report bug" + "Your account details, contacts, preferences, and chat list will be kept" + "You will lose your existing message history" + "You will need to verify all your existing devices and contacts again" + "Only reset your identity if you don’t have access to another signed-in device and you’ve lost your recovery key." + "If you’re not signed in to any other devices and you’ve lost your recovery key, then you’ll need to reset your identity to continue using the app. " + "Reset your identity in case you can’t confirm another way" "Failed selecting media, please try again." "Failed processing media to upload, please try again." "Failed uploading media, please try again." + "Yes, reset now" + "This process is irreversible." + "Are you sure you want to reset your encryption?" + "Enter…" + "Confirm that you want to reset your encryption." + "Enter your account password to continue" "Failed processing media to upload, please try again." "Could not retrieve user details" "Block" diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 4c3d1bdcde..99ccf2796d 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,40 +1,40 @@ // 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",19929,], -["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19929,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19937,], +["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19937,], ["features.invite.impl.response_AcceptDeclineInviteView_Day_0_en","features.invite.impl.response_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19929,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19929,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19929,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19929,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19937,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19937,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19937,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19937,], ["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_4_en","features.login.impl.accountprovider_AccountProviderView_Night_4_en",0,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19929,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19929,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19929,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19929,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19929,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19929,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19929,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19929,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19929,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19929,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19929,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19929,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19937,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19937,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19937,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19937,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19937,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19937,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19937,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19937,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19937,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19937,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19937,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19937,], ["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",19929,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",19937,], ["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",19929,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",19937,], ["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",19929,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",19937,], ["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",19929,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19937,], ["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,], @@ -44,11 +44,11 @@ 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","",19929,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19929,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19929,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19929,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19929,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",19937,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19937,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19937,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19937,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19937,], ["libraries.designsystem.components.avatar_Avatar_Avatars_0_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_10_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_11_en","",0,], @@ -128,13 +128,13 @@ export const screenshots = [ ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], ["libraries.designsystem.components_BigCheckmark_Day_0_en","libraries.designsystem.components_BigCheckmark_Night_0_en",0,], ["libraries.designsystem.components_BigIcon_Day_0_en","libraries.designsystem.components_BigIcon_Night_0_en",0,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19929,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19929,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19929,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19929,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19929,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19929,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19929,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19937,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19937,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19937,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19937,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19937,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19937,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19937,], ["libraries.designsystem.components_BloomInitials_Day_0_en","libraries.designsystem.components_BloomInitials_Night_0_en",0,], ["libraries.designsystem.components_BloomInitials_Day_1_en","libraries.designsystem.components_BloomInitials_Night_1_en",0,], ["libraries.designsystem.components_BloomInitials_Day_2_en","libraries.designsystem.components_BloomInitials_Night_2_en",0,], @@ -145,84 +145,84 @@ export const screenshots = [ ["libraries.designsystem.components_BloomInitials_Day_7_en","libraries.designsystem.components_BloomInitials_Night_7_en",0,], ["libraries.designsystem.components_Bloom_Day_0_en","libraries.designsystem.components_Bloom_Night_0_en",0,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19929,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19929,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19929,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19929,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19929,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19937,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19937,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19937,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19937,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19937,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_0_en","features.call.impl.ui_CallScreenPipView_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_1_en","features.call.impl.ui_CallScreenPipView_Night_1_en",0,], ["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,], -["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19929,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19929,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19929,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19929,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19929,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19929,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19929,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19929,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19929,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19929,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19929,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19937,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19937,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19937,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19937,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19937,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19937,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19937,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19937,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19937,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19937,], ["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",19929,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19929,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",19937,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19937,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19929,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19937,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], ["libraries.textcomposer.components_ComposerOptionsButton_Day_0_en","libraries.textcomposer.components_ComposerOptionsButton_Night_0_en",0,], ["libraries.designsystem.components.avatar_CompositeAvatar_Avatars_en","",0,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19929,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19929,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19937,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19937,], ["features.preferences.impl.developer.tracing_ConfigureTracingView_Day_0_en","features.preferences.impl.developer.tracing_ConfigureTracingView_Night_0_en",0,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19929,], -["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19929,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19937,], +["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19937,], ["libraries.designsystem.components.dialogs_ConfirmationDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ConfirmationDialog_Day_0_en","libraries.designsystem.components.dialogs_ConfirmationDialog_Night_0_en",0,], ["features.networkmonitor.api.ui_ConnectivityIndicatorView_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicatorView_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19929,], -["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19929,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19929,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19929,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19929,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19929,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19929,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19929,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19929,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19929,], -["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19929,], -["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19929,], -["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19929,], -["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19929,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19929,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19929,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19937,], +["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19937,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19937,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19937,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19937,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19937,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19937,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19937,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19937,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19937,], +["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19937,], +["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19937,], +["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19937,], +["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19937,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19937,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19937,], ["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",19929,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19929,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19929,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",19937,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19937,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19937,], ["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",19929,], -["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19929,], -["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19929,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19929,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19929,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19929,], -["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19929,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",19937,], +["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19937,], +["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19937,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19937,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19937,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19937,], +["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19937,], ["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,], @@ -234,12 +234,12 @@ export const screenshots = [ ["libraries.designsystem.text_DpScale_1_0f__en","",0,], ["libraries.designsystem.text_DpScale_1_5f__en","",0,], ["libraries.designsystem.theme.components_DropdownMenuItem_Menus_en","",0,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19929,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19929,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19929,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19929,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19929,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19929,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19937,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19937,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19937,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19937,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19937,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19937,], ["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,], @@ -249,10 +249,10 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiPicker_Night_0_en",0,], -["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19929,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19929,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19929,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19929,], +["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19937,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19937,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19937,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19937,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], ["libraries.designsystem.theme.components_FilledButtonLargeLowPadding_Buttons_en","",0,], @@ -263,15 +263,15 @@ export const screenshots = [ ["libraries.designsystem.theme.components_FloatingActionButton_Floating Action Buttons_en","",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19929,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19929,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19929,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19937,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19937,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19937,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_0_en","features.messages.impl.forward_ForwardMessagesView_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_1_en","features.messages.impl.forward_ForwardMessagesView_Night_1_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_2_en","features.messages.impl.forward_ForwardMessagesView_Night_2_en",0,], -["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19929,], -["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19929,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19937,], +["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19937,], ["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,], @@ -298,37 +298,37 @@ 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",19929,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",19937,], ["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",19929,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",19937,], ["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",19929,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",19937,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19929,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19937,], ["features.joinroom.impl_JoinRoomView_Day_0_en","features.joinroom.impl_JoinRoomView_Night_0_en",0,], ["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",0,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19929,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19929,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19929,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19929,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19929,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19929,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19929,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19929,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19929,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19937,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19937,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19937,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19937,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19937,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19937,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19937,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19937,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19937,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["libraries.designsystem.components_LabelledOutlinedTextField_Day_0_en","libraries.designsystem.components_LabelledOutlinedTextField_Night_0_en",0,], ["libraries.designsystem.components_LabelledTextField_Day_0_en","libraries.designsystem.components_LabelledTextField_Night_0_en",0,], ["features.leaveroom.api_LeaveRoomView_Day_0_en","features.leaveroom.api_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19929,], -["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19929,], -["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19929,], -["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19929,], -["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19929,], -["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19929,], +["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19937,], +["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19937,], +["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19937,], +["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19937,], +["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19937,], +["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19937,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], @@ -379,28 +379,28 @@ 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",19929,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19929,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19929,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19929,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19937,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19937,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19937,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19937,], ["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",19929,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19929,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19929,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19929,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19929,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19929,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19929,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19929,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19929,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19929,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19929,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19929,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19929,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19929,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19929,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",19937,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19937,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19937,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19937,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19937,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19937,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19937,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19937,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19937,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19937,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19937,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19937,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19937,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19937,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19937,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19929,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19937,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en","libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_0_en","libraries.matrix.ui.components_MatrixUserHeader_Night_0_en",0,], @@ -410,7 +410,7 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_10_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19929,], +["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19937,], ["libraries.mediaviewer.api.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_5_en","",0,], @@ -420,10 +420,10 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_9_en","",0,], ["libraries.designsystem.theme.components_MediumTopAppBar_App Bars_en","",0,], ["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,], -["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19929,], +["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19937,], ["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",19929,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",19937,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_10_en","features.messages.impl.timeline.components_MessageEventBubble_Night_10_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_11_en","features.messages.impl.timeline.components_MessageEventBubble_Night_11_en",0,], @@ -447,25 +447,26 @@ 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.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19929,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19929,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19937,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19937,], ["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",0,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19929,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19929,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19929,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19929,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19937,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19937,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19937,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19937,], +["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",0,], ["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",0,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19929,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19929,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19929,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19929,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19929,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19929,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19929,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19929,], -["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19929,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19937,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19937,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19937,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19937,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19937,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19937,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19937,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19937,], +["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19937,], ["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",19929,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",19937,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -474,28 +475,28 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple selection List item - selection in trailing content_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple selection List item - selection in supporting text_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple selection List item - no selection_List items_en","",0,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19929,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19929,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19929,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19937,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19937,], ["features.login.impl.oidc.webview_OidcView_Day_0_en","features.login.impl.oidc.webview_OidcView_Night_0_en",0,], ["features.login.impl.oidc.webview_OidcView_Day_1_en","features.login.impl.oidc.webview_OidcView_Night_1_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19929,], -["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19929,], -["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19929,], -["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19929,], -["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19929,], +["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19937,], +["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19937,], +["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19937,], +["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19937,], +["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19937,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], @@ -510,47 +511,53 @@ export const screenshots = [ ["libraries.designsystem.components_PageTitleWithIconFull_Day_3_en","libraries.designsystem.components_PageTitleWithIconFull_Night_3_en",0,], ["libraries.designsystem.components_PageTitleWithIconFull_Day_4_en","libraries.designsystem.components_PageTitleWithIconFull_Night_4_en",0,], ["libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en","libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en",0,], -["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19929,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19929,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19929,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19929,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19929,], +["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19937,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19937,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19937,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19937,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19937,], ["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",19929,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19929,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19929,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19937,], +["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_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",0,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",0,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",0,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",0,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",0,], ["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",19929,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19929,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19929,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19929,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19929,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19937,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19937,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19937,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19937,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19937,], ["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",19929,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19929,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19929,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19929,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19929,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19929,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19929,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19929,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19929,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19929,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19929,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",19937,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19937,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19937,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19937,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19937,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19937,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19937,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19937,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19937,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19937,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19937,], ["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceDivider_Preferences_en","",0,], @@ -566,182 +573,182 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceTextLight_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19929,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19929,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19929,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19929,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19937,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19937,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19937,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19937,], ["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","",19929,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19929,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19929,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19929,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19929,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19929,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19929,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19929,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19929,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19929,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19929,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19929,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19929,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19929,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19929,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19929,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19929,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19929,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",19937,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19937,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19937,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19937,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19937,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19937,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19937,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19937,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19937,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19937,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19937,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19937,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19937,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19937,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19937,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19937,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19937,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19937,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19929,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19929,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19937,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19937,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19929,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19929,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19929,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19929,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19929,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19929,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19929,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19937,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19937,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19937,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19937,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19937,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19937,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19937,], ["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",19929,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19929,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19929,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19929,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19929,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19929,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19929,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19929,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19929,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19929,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19929,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19929,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19929,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19929,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19929,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19929,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19937,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19937,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19937,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19937,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19937,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19937,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19937,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19937,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19937,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19937,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19937,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19937,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19937,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19937,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19937,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19937,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19929,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19937,], ["features.roomdetails.impl.components_RoomBadgeNegative_Day_0_en","features.roomdetails.impl.components_RoomBadgeNegative_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgeNeutral_Day_0_en","features.roomdetails.impl.components_RoomBadgeNeutral_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgePositive_Day_0_en","features.roomdetails.impl.components_RoomBadgePositive_Night_0_en",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",19929,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",19929,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19929,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19929,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19929,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19929,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19929,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19929,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19929,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19929,], -["features.roomdetails.impl_RoomDetails_0_en","",19929,], -["features.roomdetails.impl_RoomDetails_10_en","",19929,], -["features.roomdetails.impl_RoomDetails_11_en","",19929,], -["features.roomdetails.impl_RoomDetails_12_en","",19929,], -["features.roomdetails.impl_RoomDetails_1_en","",19929,], -["features.roomdetails.impl_RoomDetails_2_en","",19929,], -["features.roomdetails.impl_RoomDetails_3_en","",19929,], -["features.roomdetails.impl_RoomDetails_4_en","",19929,], -["features.roomdetails.impl_RoomDetails_5_en","",19929,], -["features.roomdetails.impl_RoomDetails_6_en","",19929,], -["features.roomdetails.impl_RoomDetails_7_en","",19929,], -["features.roomdetails.impl_RoomDetails_8_en","",19929,], -["features.roomdetails.impl_RoomDetails_9_en","",19929,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19929,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19929,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19929,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19929,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19929,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19929,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19929,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19929,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19929,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19929,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19929,], -["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19929,], -["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19929,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",19937,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",19937,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19937,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19937,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19937,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19937,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19937,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19937,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19937,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19937,], +["features.roomdetails.impl_RoomDetails_0_en","",19937,], +["features.roomdetails.impl_RoomDetails_10_en","",19937,], +["features.roomdetails.impl_RoomDetails_11_en","",19937,], +["features.roomdetails.impl_RoomDetails_12_en","",19937,], +["features.roomdetails.impl_RoomDetails_1_en","",19937,], +["features.roomdetails.impl_RoomDetails_2_en","",19937,], +["features.roomdetails.impl_RoomDetails_3_en","",19937,], +["features.roomdetails.impl_RoomDetails_4_en","",19937,], +["features.roomdetails.impl_RoomDetails_5_en","",19937,], +["features.roomdetails.impl_RoomDetails_6_en","",19937,], +["features.roomdetails.impl_RoomDetails_7_en","",19937,], +["features.roomdetails.impl_RoomDetails_8_en","",19937,], +["features.roomdetails.impl_RoomDetails_9_en","",19937,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19937,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19937,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19937,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19937,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19937,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19937,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19937,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19937,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19937,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19937,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19937,], +["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19937,], +["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19937,], ["features.roomlist.impl.components_RoomListContentView_Day_2_en","features.roomlist.impl.components_RoomListContentView_Night_2_en",0,], -["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19929,], -["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19929,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19929,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19929,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19929,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19929,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19929,], +["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19937,], +["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19937,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19937,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19937,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19937,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19937,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19937,], ["features.roomlist.impl.search_RoomListSearchContent_Day_0_en","features.roomlist.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19929,], -["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19929,], -["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19929,], +["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19937,], +["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19937,], +["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19937,], ["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",0,], -["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19929,], -["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19929,], -["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19929,], -["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19929,], -["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19929,], -["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19929,], -["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19929,], +["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19937,], +["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19937,], +["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19937,], +["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19937,], +["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19937,], +["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19937,], +["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19937,], ["features.roomlist.impl_RoomListView_Day_8_en","features.roomlist.impl_RoomListView_Night_8_en",0,], -["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19929,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19929,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19929,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19929,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19929,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19929,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19929,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19929,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19929,], +["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19937,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19937,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19937,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19937,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19937,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19937,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19937,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19937,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19937,], ["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19929,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19929,], -["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19929,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19937,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19937,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19937,], ["libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Day_0_en","libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Night_0_en",0,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19929,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19929,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19929,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19929,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19929,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19929,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19929,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19929,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19929,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19937,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19937,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19937,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19937,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19937,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19937,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19937,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19937,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19937,], ["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_9_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19929,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19929,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19929,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19929,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19929,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19929,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19929,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19929,], -["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19929,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19929,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19929,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19929,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19929,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19929,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19929,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19937,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19937,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19937,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19937,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19937,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19937,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19937,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19937,], +["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19937,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19937,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19937,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19937,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19937,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19937,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19937,], ["features.roomlist.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.roomlist.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_0_en","features.roomlist.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_10_en","features.roomlist.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -764,10 +771,10 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_26_en","features.roomlist.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_27_en","features.roomlist.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_28_en","features.roomlist.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19929,], -["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19929,], -["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19929,], -["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19929,], +["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19937,], +["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19937,], +["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19937,], +["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19937,], ["features.roomlist.impl.components_RoomSummaryRow_Day_3_en","features.roomlist.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_4_en","features.roomlist.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_5_en","features.roomlist.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -775,64 +782,64 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_7_en","features.roomlist.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_8_en","features.roomlist.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_9_en","features.roomlist.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19929,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19929,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19929,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19937,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19937,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19937,], ["appicon.element_RoundIcon_en","",0,], ["appicon.enterprise_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",19929,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19929,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19929,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",19937,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19937,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19937,], ["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","",19929,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search views_en","",19937,], ["libraries.designsystem.theme.components_SearchBarActiveWithQueryNoBackButton_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithQuery_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarInactive_Search views_en","",0,], -["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19929,], -["features.createroom.impl.components_SearchSingleUserResultItem_en","",19929,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19929,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19929,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19929,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19929,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19929,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19929,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19929,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19929,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19929,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19929,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19929,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19929,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19929,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19929,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19929,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19929,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19929,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19929,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19929,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19929,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19929,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19929,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19929,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19929,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19929,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19929,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19929,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19929,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19929,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19929,], +["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19937,], +["features.createroom.impl.components_SearchSingleUserResultItem_en","",19937,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19937,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19937,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19937,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19937,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19937,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19937,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19937,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19937,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19937,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19937,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19937,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19937,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19937,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19937,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19937,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19937,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19937,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19937,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19937,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19937,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19937,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19937,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19937,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19937,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19937,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19937,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19937,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19937,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19937,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19937,], ["libraries.matrix.ui.components_SelectedRoom_Day_0_en","libraries.matrix.ui.components_SelectedRoom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoom_Day_1_en","libraries.matrix.ui.components_SelectedRoom_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en","libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUser_Day_0_en","libraries.matrix.ui.components_SelectedUser_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19929,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19929,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19929,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19929,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19929,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19937,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19937,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19937,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19937,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19937,], ["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,], @@ -842,37 +849,37 @@ 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.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19929,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19929,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19929,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19929,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19929,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19929,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19937,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19937,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19937,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19937,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19937,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19937,], ["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",19929,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",19937,], ["features.messages.impl.timeline.components.reactionsummary_SheetContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_SheetContent_Night_0_en",0,], ["features.messages.impl.actionlist_SheetContent_Day_0_en","features.messages.impl.actionlist_SheetContent_Night_0_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19929,], +["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19937,], ["features.messages.impl.actionlist_SheetContent_Day_1_en","features.messages.impl.actionlist_SheetContent_Night_1_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19929,], -["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19929,], -["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19929,], -["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19929,], -["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19929,], -["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19929,], -["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19929,], -["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19929,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19929,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19929,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19929,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19929,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19929,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19929,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19929,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19929,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19929,], +["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19937,], +["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19937,], +["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19937,], +["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19937,], +["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19937,], +["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19937,], +["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19937,], +["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19937,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19937,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19937,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19937,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19937,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19937,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19937,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19937,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19937,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19937,], ["libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en",0,], ["libraries.designsystem.components.list_SingleSelectionListItemCustomFormattert_Single selection List item - custom formatter_List items_en","",0,], @@ -881,7 +888,7 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single selection List item - no selection, supporting text_List items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single selection List item - no selection_List items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19929,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19937,], ["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,], @@ -891,36 +898,36 @@ export const screenshots = [ ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], ["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",0,], -["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19929,], +["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19937,], ["features.location.api_StaticMapView_Day_0_en","features.location.api_StaticMapView_Night_0_en",0,], ["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",19929,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",19937,], ["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_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19929,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19929,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19929,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19929,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19929,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19929,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19929,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19937,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19937,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19937,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19937,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19937,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19937,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19937,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], ["libraries.designsystem.theme.components_TextFieldDark_TextFields_en","",0,], @@ -932,38 +939,38 @@ export const screenshots = [ ["libraries.designsystem.theme.components_TextFieldValueTextFieldDark_TextFields_en","",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19929,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19929,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19929,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19937,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19937,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19937,], ["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",19929,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19929,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",19937,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19937,], ["features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en",0,], ["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_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19929,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19937,], ["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",19929,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19929,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19929,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",19937,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19937,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19937,], ["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,], ["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",19929,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19929,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19929,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19937,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19937,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19937,], ["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",19929,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19929,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",19937,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19937,], ["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,], @@ -972,36 +979,36 @@ 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",19929,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19937,], ["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",19929,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19937,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19929,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19937,], ["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_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19929,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19929,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19937,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19937,], ["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_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",19929,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",19937,], ["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",19929,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19929,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19929,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19929,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19929,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19937,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19937,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19937,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19937,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19937,], ["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",19929,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19929,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",19937,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19937,], ["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",19929,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",19937,], ["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,], @@ -1010,8 +1017,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",19929,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19929,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",19937,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19937,], ["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,], @@ -1023,7 +1030,7 @@ 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",19929,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",19937,], ["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,], @@ -1045,79 +1052,79 @@ 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_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19929,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19937,], ["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",19929,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19929,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19929,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19929,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19929,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19929,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19929,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19937,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19937,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19937,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19937,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19937,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19937,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19937,], ["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",19929,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",19937,], ["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",19929,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",19937,], ["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",19929,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",19937,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.theme.components_TopAppBar_App Bars_en","",0,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19929,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19929,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19929,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19929,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19929,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19929,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19929,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19929,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19937,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19937,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19937,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19937,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19937,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19937,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19937,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19937,], ["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",19929,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19929,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19929,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19929,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19929,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19929,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",19937,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19937,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19937,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19937,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19937,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19937,], ["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","",19929,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",19937,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19929,], -["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19929,], -["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19929,], -["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19929,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19937,], +["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19937,], +["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19937,], +["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19937,], ["features.createroom.impl.components_UserListView_Day_3_en","features.createroom.impl.components_UserListView_Night_3_en",0,], ["features.createroom.impl.components_UserListView_Day_4_en","features.createroom.impl.components_UserListView_Night_4_en",0,], ["features.createroom.impl.components_UserListView_Day_5_en","features.createroom.impl.components_UserListView_Night_5_en",0,], ["features.createroom.impl.components_UserListView_Day_6_en","features.createroom.impl.components_UserListView_Night_6_en",0,], -["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19929,], +["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19937,], ["features.createroom.impl.components_UserListView_Day_8_en","features.createroom.impl.components_UserListView_Night_8_en",0,], -["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19929,], +["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19937,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], ["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",0,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19929,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19929,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19929,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19929,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19929,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19929,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19929,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19929,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19929,], -["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19929,], -["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19929,], -["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19929,], -["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19929,], -["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19929,], -["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19929,], -["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19929,], -["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19929,], -["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19929,], -["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19929,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19937,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19937,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19937,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19937,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19937,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19937,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19937,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19937,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19937,], +["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19937,], +["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19937,], +["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19937,], +["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19937,], +["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19937,], +["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19937,], +["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19937,], +["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19937,], +["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19937,], +["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19937,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,], @@ -1131,12 +1138,12 @@ export const screenshots = [ ["libraries.textcomposer.components_VoiceMessageRecorderButton_Day_0_en","libraries.textcomposer.components_VoiceMessageRecorderButton_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessageRecording_Day_0_en","libraries.textcomposer.components_VoiceMessageRecording_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessage_Day_0_en","libraries.textcomposer.components_VoiceMessage_Night_0_en",0,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19929,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19929,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19929,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19929,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19929,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19937,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19937,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19937,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19937,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19937,], ["libraries.designsystem.components.media_WaveformPlaybackView_Day_0_en","libraries.designsystem.components.media_WaveformPlaybackView_Night_0_en",0,], -["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19929,], +["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19937,], ["libraries.designsystem.ruler_WithRulers_Day_0_en","libraries.designsystem.ruler_WithRulers_Night_0_en",0,], ]; From f93176af373393e1e93d5c1c91f251e5aee237b8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 09:33:24 +0000 Subject: [PATCH 062/186] Update dependency org.matrix.rustcomponents:sdk-android to v0.2.36 --- 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 d04849d390..a3211068d4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.35" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.36" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From 16bef2a277d97a6438c896ca6b090ed9f1f775a9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 06:58:45 +0000 Subject: [PATCH 063/186] Update wysiwyg to v2.37.8 (#3263) 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 a3211068d4..bd554061ae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -44,7 +44,7 @@ serialization_json = "1.6.3" showkase = "1.0.3" appyx = "1.4.0" sqldelight = "2.0.2" -wysiwyg = "2.37.7" +wysiwyg = "2.37.8" telephoto = "0.12.1" # DI From 80f1574b6603e728a329431b5aeb0182a481f4d0 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 6 Aug 2024 15:08:02 +0200 Subject: [PATCH 064/186] Pinned events : update sdk --- gradle/libs.versions.toml | 2 +- .../impl/timeline/item/event/TimelineEventContentMapper.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a3211068d4..686f3b5b20 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.36" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.37" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt index 6b0da71eee..90b13e356d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt @@ -176,7 +176,7 @@ private fun RustOtherState.map(): OtherState { RustOtherState.RoomHistoryVisibility -> OtherState.RoomHistoryVisibility RustOtherState.RoomJoinRules -> OtherState.RoomJoinRules is RustOtherState.RoomName -> OtherState.RoomName(name) - RustOtherState.RoomPinnedEvents -> OtherState.RoomPinnedEvents + is RustOtherState.RoomPinnedEvents -> OtherState.RoomPinnedEvents is RustOtherState.RoomPowerLevels -> OtherState.RoomUserPowerLevels(users) RustOtherState.RoomServerAcl -> OtherState.RoomServerAcl is RustOtherState.RoomThirdPartyInvite -> OtherState.RoomThirdPartyInvite(displayName) From 50fd2558dea06998381f3c5caa9b7ca8b7ac0d31 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 6 Aug 2024 15:08:45 +0200 Subject: [PATCH 065/186] Pinned events : handle loading/error on banner --- .../messages/impl/MessagesStateProvider.kt | 8 +- .../features/messages/impl/MessagesView.kt | 3 +- .../banner/PinnedMessagesBannerPresenter.kt | 91 ++++++++--- .../banner/PinnedMessagesBannerState.kt | 43 ++++- .../PinnedMessagesBannerStateProvider.kt | 36 +++-- .../pinned/banner/PinnedMessagesBannerView.kt | 149 ++++++++++++------ .../messages/impl/MessagesPresenterTest.kt | 4 +- .../src/main/res/values/localazy.xml | 1 + 8 files changed, 238 insertions(+), 97 deletions(-) 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 a1b7bc6ad1..97436c2bc0 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 @@ -23,7 +23,7 @@ import io.element.android.features.messages.impl.messagecomposer.AttachmentsStat import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState -import io.element.android.features.messages.impl.pinned.banner.aPinnedMessagesBannerState +import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.TimelineState import io.element.android.features.messages.impl.timeline.aTimelineItemList import io.element.android.features.messages.impl.timeline.aTimelineState @@ -90,8 +90,8 @@ open class MessagesStateProvider : PreviewParameterProvider { callState = RoomCallState.DISABLED, ), aMessagesState( - pinnedMessagesBannerState = aPinnedMessagesBannerState( - pinnedMessagesCount = 4, + pinnedMessagesBannerState = aLoadedPinnedMessagesBannerState( + knownPinnedMessagesCount = 4, currentPinnedMessageIndex = 0, ), ), @@ -121,7 +121,7 @@ fun aMessagesState( showReinvitePrompt: Boolean = false, enableVoiceMessages: Boolean = true, callState: RoomCallState = RoomCallState.ENABLED, - pinnedMessagesBannerState: PinnedMessagesBannerState = aPinnedMessagesBannerState(), + pinnedMessagesBannerState: PinnedMessagesBannerState = aLoadedPinnedMessagesBannerState(), eventSink: (MessagesEvents) -> Unit = {}, ) = MessagesState( roomId = RoomId("!id:domain"), 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 d983404f9b..f365d917f0 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 @@ -71,6 +71,7 @@ import io.element.android.features.messages.impl.messagecomposer.AttachmentsBott import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerView +import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerView import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerViewDefaults import io.element.android.features.messages.impl.timeline.TimelineEvents @@ -400,7 +401,7 @@ private fun MessagesViewContent( nestedScrollConnection = scrollBehavior.nestedScrollConnection, ) AnimatedVisibility( - visible = state.pinnedMessagesBannerState.displayBanner && scrollBehavior.isVisible, + visible = state.pinnedMessagesBannerState != PinnedMessagesBannerState.Hidden && scrollBehavior.isVisible, enter = expandVertically(), exit = shrinkVertically(), ) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index 16b8c97af7..59bf1c5a2f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -26,10 +26,14 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import io.element.android.features.networkmonitor.api.NetworkMonitor 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.room.MatrixRoom +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn @@ -43,29 +47,34 @@ class PinnedMessagesBannerPresenter @Inject constructor( private val room: MatrixRoom, private val itemFactory: PinnedMessagesBannerItemFactory, private val featureFlagService: FeatureFlagService, + private val networkMonitor: NetworkMonitor, ) : Presenter { @Composable override fun present(): PinnedMessagesBannerState { + val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false) + var timelineFailed by rememberSaveable { mutableStateOf(false) } var pinnedItems by remember { - mutableStateOf>(emptyList()) - } - - fun onItemsChange(newItems: List) { - pinnedItems = newItems + mutableStateOf>(persistentListOf()) } + val knownPinnedMessagesCount by remember { + room.roomInfoFlow.map { roomInfo -> roomInfo.pinnedEventIds.size } + }.collectAsState(initial = null) - var currentPinnedMessageIndex by rememberSaveable { - mutableIntStateOf(0) - } + var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(0) } - LaunchedEffect(pinnedItems) { - val pinnedMessageCount = pinnedItems.size - if (currentPinnedMessageIndex >= pinnedMessageCount) { - currentPinnedMessageIndex = (pinnedMessageCount - 1).coerceAtLeast(0) + PinnedMessagesBannerItemsEffect( + isFeatureEnabled = isFeatureEnabled, + onItemsChange = { newItems -> + val pinnedMessageCount = newItems.size + if (currentPinnedMessageIndex >= pinnedMessageCount) { + currentPinnedMessageIndex = 0 + } + pinnedItems = newItems + }, + onTimelineFail = { hasTimelineFailed -> + timelineFailed = hasTimelineFailed } - } - - PinnedMessagesBannerItemsEffect(::onItemsChange) + ) fun handleEvent(event: PinnedMessagesBannerEvents) { when (event) { @@ -79,32 +88,68 @@ class PinnedMessagesBannerPresenter @Inject constructor( } } - return PinnedMessagesBannerState( - pinnedMessagesCount = pinnedItems.size, - currentPinnedMessage = pinnedItems.getOrNull(currentPinnedMessageIndex), + return pinnedMessagesBannerState( + isFeatureEnabled = isFeatureEnabled, + hasTimelineFailed = timelineFailed, + realPinnedMessagesCount = knownPinnedMessagesCount, + pinnedItems = pinnedItems, currentPinnedMessageIndex = currentPinnedMessageIndex, eventSink = ::handleEvent ) } + @Composable + private fun pinnedMessagesBannerState( + isFeatureEnabled: Boolean, + hasTimelineFailed: Boolean, + realPinnedMessagesCount: Int?, + pinnedItems: ImmutableList, + currentPinnedMessageIndex: Int, + eventSink: (PinnedMessagesBannerEvents) -> Unit + ): PinnedMessagesBannerState { + val currentPinnedMessage = pinnedItems.getOrNull(currentPinnedMessageIndex) + return when { + !isFeatureEnabled -> PinnedMessagesBannerState.Hidden + hasTimelineFailed -> PinnedMessagesBannerState.Hidden + realPinnedMessagesCount == null || realPinnedMessagesCount == 0 -> PinnedMessagesBannerState.Hidden + currentPinnedMessage == null -> PinnedMessagesBannerState.Loading(realPinnedMessagesCount = realPinnedMessagesCount) + else -> { + PinnedMessagesBannerState.Loaded( + currentPinnedMessage = currentPinnedMessage, + currentPinnedMessageIndex = currentPinnedMessageIndex, + knownPinnedMessagesCount = realPinnedMessagesCount, + eventSink = eventSink + ) + } + } + } + @OptIn(FlowPreview::class) @Composable private fun PinnedMessagesBannerItemsEffect( - onItemsChange: (List) -> Unit, + isFeatureEnabled: Boolean, + onItemsChange: (ImmutableList) -> Unit, + onTimelineFail: (Boolean) -> Unit, ) { - val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false) val updatedOnItemsChange by rememberUpdatedState(onItemsChange) + val updatedOnTimelineFail by rememberUpdatedState(onTimelineFail) + val networkStatus by networkMonitor.connectivity.collectAsState() - LaunchedEffect(isFeatureEnabled) { + LaunchedEffect(isFeatureEnabled, networkStatus) { if (!isFeatureEnabled) return@LaunchedEffect - val pinnedEventsTimeline = room.pinnedEventsTimeline().getOrNull() ?: return@LaunchedEffect + val pinnedEventsTimeline = room.pinnedEventsTimeline() + .onFailure { updatedOnTimelineFail(true) } + .onSuccess { updatedOnTimelineFail(false) } + .getOrNull() + ?: return@LaunchedEffect + pinnedEventsTimeline.timelineItems .debounce(300.milliseconds) .map { timelineItems -> timelineItems.mapNotNull { timelineItem -> itemFactory.create(timelineItem) - } + }.toImmutableList() } .onEach { newItems -> updatedOnItemsChange(newItems) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt index b607855058..886cef81de 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt @@ -16,11 +16,40 @@ package io.element.android.features.messages.impl.pinned.banner -data class PinnedMessagesBannerState( - val pinnedMessagesCount: Int, - val currentPinnedMessageIndex: Int, - val currentPinnedMessage: PinnedMessagesBannerItem?, - val eventSink: (PinnedMessagesBannerEvents) -> Unit -) { - val displayBanner = pinnedMessagesCount > 0 && currentPinnedMessage != null +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import io.element.android.libraries.designsystem.text.toAnnotatedString +import io.element.android.libraries.ui.strings.CommonStrings + +@Immutable +sealed interface PinnedMessagesBannerState { + data object Hidden : PinnedMessagesBannerState + data class Loading(val realPinnedMessagesCount: Int) : PinnedMessagesBannerState + data class Loaded( + val currentPinnedMessage: PinnedMessagesBannerItem, + val currentPinnedMessageIndex: Int, + val knownPinnedMessagesCount: Int, + val eventSink: (PinnedMessagesBannerEvents) -> Unit + ) : PinnedMessagesBannerState + + fun pinnedMessagesCount() = when (this) { + is Hidden -> 0 + is Loading -> realPinnedMessagesCount + is Loaded -> knownPinnedMessagesCount + } + + fun currentPinnedMessageIndex() = when (this) { + is Hidden -> 0 + is Loading -> 0 + is Loaded -> currentPinnedMessageIndex + } + + @Composable + fun formattedMessage() = when (this) { + is Hidden -> AnnotatedString("") + is Loading -> stringResource(id = CommonStrings.screen_room_pinned_banner_loading_description).toAnnotatedString() + is Loaded -> currentPinnedMessage.formatted + } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt index dcd6a4984a..bdcab879fe 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt @@ -24,26 +24,38 @@ import kotlin.random.Random internal class PinnedMessagesBannerStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - aPinnedMessagesBannerState(pinnedMessagesCount = 1, currentPinnedMessageIndex = 0), - aPinnedMessagesBannerState(pinnedMessagesCount = 2, currentPinnedMessageIndex = 0), - aPinnedMessagesBannerState(pinnedMessagesCount = 4, currentPinnedMessageIndex = 0), - aPinnedMessagesBannerState(pinnedMessagesCount = 4, currentPinnedMessageIndex = 1), - aPinnedMessagesBannerState(pinnedMessagesCount = 4, currentPinnedMessageIndex = 2), - aPinnedMessagesBannerState(pinnedMessagesCount = 4, currentPinnedMessageIndex = 3), + aHiddenPinnedMessagesBannerState(), + aLoadingPinnedMessagesBannerState(knownPinnedMessagesCount = 1), + aLoadingPinnedMessagesBannerState(knownPinnedMessagesCount = 4), + aLoadedPinnedMessagesBannerState(knownPinnedMessagesCount = 1, currentPinnedMessageIndex = 0), + aLoadedPinnedMessagesBannerState(knownPinnedMessagesCount = 2, currentPinnedMessageIndex = 0), + aLoadedPinnedMessagesBannerState(knownPinnedMessagesCount = 3, currentPinnedMessageIndex = 0), + aLoadedPinnedMessagesBannerState(knownPinnedMessagesCount = 4, currentPinnedMessageIndex = 0), + aLoadedPinnedMessagesBannerState(knownPinnedMessagesCount = 4, currentPinnedMessageIndex = 1), + aLoadedPinnedMessagesBannerState(knownPinnedMessagesCount = 4, currentPinnedMessageIndex = 2), + aLoadedPinnedMessagesBannerState(knownPinnedMessagesCount = 4, currentPinnedMessageIndex = 3), ) } -internal fun aPinnedMessagesBannerState( - pinnedMessagesCount: Int = 0, - currentPinnedMessageIndex: Int = -1, +internal fun aHiddenPinnedMessagesBannerState() = PinnedMessagesBannerState.Hidden + +internal fun aLoadingPinnedMessagesBannerState( + knownPinnedMessagesCount: Int = 4 +) = PinnedMessagesBannerState.Loading( + realPinnedMessagesCount = knownPinnedMessagesCount +) + +internal fun aLoadedPinnedMessagesBannerState( + currentPinnedMessageIndex: Int = 0, + knownPinnedMessagesCount: Int = 1, currentPinnedMessage: PinnedMessagesBannerItem = PinnedMessagesBannerItem( eventId = EventId("\$" + Random.nextInt().toString()), formatted = AnnotatedString("This is a pinned message") ), eventSink: (PinnedMessagesBannerEvents) -> Unit = {} -) = PinnedMessagesBannerState( - pinnedMessagesCount = pinnedMessagesCount, - currentPinnedMessageIndex = currentPinnedMessageIndex, +) = PinnedMessagesBannerState.Loaded( currentPinnedMessage = currentPinnedMessage, + currentPinnedMessageIndex = currentPinnedMessageIndex, + knownPinnedMessagesCount = knownPinnedMessagesCount, eventSink = eventSink ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index 0ddbe1ed7b..b7524e43df 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -71,42 +71,52 @@ fun PinnedMessagesBannerView( onViewAllClick: () -> Unit, modifier: Modifier = Modifier, ) { - if (state.currentPinnedMessage == null) return + Box(modifier = modifier) { + when (state) { + PinnedMessagesBannerState.Hidden -> Unit + is PinnedMessagesBannerState.Loading -> { + PinnedMessagesBannerRow( + state = state, + onViewAllClick = onViewAllClick, + modifier = Modifier.clickable(onClick = { }), + ) + } + is PinnedMessagesBannerState.Loaded -> { + fun onClick() { + onClick(state.currentPinnedMessage.eventId) + state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + } + PinnedMessagesBannerRow( + state = state, + onViewAllClick = onViewAllClick, + modifier = Modifier.clickable(onClick = ::onClick), + ) + } + } + } +} + +@Composable +fun PinnedMessagesBannerRow( + state: PinnedMessagesBannerState, + onViewAllClick: () -> Unit, + modifier: Modifier = Modifier, +) { val borderColor = ElementTheme.colors.pinnedMessageBannerBorder Row( modifier = modifier - .background(color = ElementTheme.colors.bgCanvasDefault) - .fillMaxWidth() - .drawBehind { - val strokeWidth = 0.5.dp.toPx() - val y = size.height - strokeWidth / 2 - drawLine( - borderColor, - Offset(0f, y), - Offset(size.width, y), - strokeWidth - ) - drawLine( - borderColor, - Offset(0f, 0f), - Offset(size.width, 0f), - strokeWidth - ) - } - .shadow(elevation = 5.dp, spotColor = Color.Transparent) - .heightIn(min = 64.dp) - .clickable { - onClick(state.currentPinnedMessage.eventId) - state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) - }, + .background(color = ElementTheme.colors.bgCanvasDefault) + .fillMaxWidth() + .drawBorder(borderColor) + .heightIn(min = 64.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = spacedBy(10.dp) ) { Spacer(modifier = Modifier.width(16.dp)) PinIndicators( - pinIndex = state.currentPinnedMessageIndex, - pinsCount = state.pinnedMessagesCount, + pinIndex = state.currentPinnedMessageIndex(), + pinsCount = state.pinnedMessagesCount(), modifier = Modifier.heightIn(max = 40.dp) ) Icon( @@ -116,15 +126,56 @@ fun PinnedMessagesBannerView( modifier = Modifier.size(20.dp) ) PinnedMessageItem( - index = state.currentPinnedMessageIndex, - totalCount = state.pinnedMessagesCount, - message = state.currentPinnedMessage.formatted, + index = state.currentPinnedMessageIndex(), + totalCount = state.pinnedMessagesCount(), + message = state.formattedMessage(), modifier = Modifier.weight(1f) ) - TextButton(text = stringResource(id = CommonStrings.screen_room_pinned_banner_view_all_button_title), onClick = onViewAllClick) + ViewAllButton(state, onViewAllClick) } } +@Composable +private fun ViewAllButton( + state: PinnedMessagesBannerState, + onViewAllClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Box(modifier = modifier) { + val text = if (state is PinnedMessagesBannerState.Loaded) { + stringResource(id = CommonStrings.screen_room_pinned_banner_view_all_button_title) + } else { + "" + } + TextButton( + text = text, + showProgress = state is PinnedMessagesBannerState.Loading, + onClick = onViewAllClick + ) + } +} + +private fun Modifier.drawBorder(borderColor: Color): Modifier { + return this + .drawBehind { + val strokeWidth = 0.5.dp.toPx() + val y = size.height - strokeWidth / 2 + drawLine( + borderColor, + Offset(0f, y), + Offset(size.width, y), + strokeWidth + ) + drawLine( + borderColor, + Offset(0f, 0f), + Offset(size.width, 0f), + strokeWidth + ) + } + .shadow(elevation = 5.dp, spotColor = Color.Transparent) +} + @Composable private fun PinIndicators( pinIndex: Int, @@ -157,15 +208,15 @@ private fun PinIndicators( items(pinsCount) { index -> Box( modifier = Modifier - .width(2.dp) - .height(indicatorHeight.dp) - .background( - color = if (index == pinIndex) { - ElementTheme.colors.iconAccentPrimary - } else { - ElementTheme.colors.pinnedMessageBannerIndicator - } - ) + .width(2.dp) + .height(indicatorHeight.dp) + .background( + color = if (index == pinIndex) { + ElementTheme.colors.iconAccentPrimary + } else { + ElementTheme.colors.pinnedMessageBannerIndicator + } + ) ) } } @@ -175,7 +226,7 @@ private fun PinIndicators( private fun PinnedMessageItem( index: Int, totalCount: Int, - message: AnnotatedString, + message: AnnotatedString?, modifier: Modifier = Modifier, ) { val countMessage = stringResource(id = CommonStrings.screen_room_pinned_banner_indicator, index + 1, totalCount) @@ -193,13 +244,15 @@ private fun PinnedMessageItem( overflow = TextOverflow.Ellipsis, ) } - Text( - text = message, - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textPrimary, - overflow = TextOverflow.Ellipsis, - maxLines = 1, - ) + if (message != null) { + Text( + text = message, + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textPrimary, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + ) + } } } 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 d04c0974e0..a6c123971b 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 @@ -30,7 +30,7 @@ import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactory import io.element.android.features.messages.impl.messagecomposer.DefaultMessageComposerContext import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter -import io.element.android.features.messages.impl.pinned.banner.aPinnedMessagesBannerState +import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState import io.element.android.features.messages.impl.textcomposer.TestRichTextEditorStateFactory import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.timeline.TimelineItemIndexer @@ -1072,7 +1072,7 @@ class MessagesPresenterTest { customReactionPresenter = customReactionPresenter, reactionSummaryPresenter = reactionSummaryPresenter, readReceiptBottomSheetPresenter = readReceiptBottomSheetPresenter, - pinnedMessagesBannerPresenter = { aPinnedMessagesBannerState() }, + pinnedMessagesBannerPresenter = { aLoadedPinnedMessagesBannerState() }, networkMonitor = FakeNetworkMonitor(), snackbarDispatcher = SnackbarDispatcher(), navigator = navigator, diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 5766c900dd..c66d504ea8 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -293,6 +293,7 @@ Reason: %1$s." "Unblock user" "%1$s of %2$s" "%1$s Pinned messages" + "Loading message…" "View All" "Chat" "Share location" From 0390ede2ad9d16c392df0ae271d908c4aa1cd78d Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 6 Aug 2024 16:13:30 +0200 Subject: [PATCH 066/186] Pinned events: add tests on PinnedMessagesBannerPresenter --- .../banner/PinnedMessagesBannerPresenter.kt | 16 +- .../PinnedMessagesBannerPresenterTest.kt | 157 ++++++++++++++++-- 2 files changed, 154 insertions(+), 19 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index 59bf1c5a2f..6604114fc5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -52,15 +52,15 @@ class PinnedMessagesBannerPresenter @Inject constructor( @Composable override fun present(): PinnedMessagesBannerState { val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false) - var timelineFailed by rememberSaveable { mutableStateOf(false) } - var pinnedItems by remember { - mutableStateOf>(persistentListOf()) - } + var hasTimelineFailedToLoad by rememberSaveable { mutableStateOf(false) } + var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(0) } val knownPinnedMessagesCount by remember { room.roomInfoFlow.map { roomInfo -> roomInfo.pinnedEventIds.size } }.collectAsState(initial = null) - var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(0) } + var pinnedItems by remember { + mutableStateOf>(persistentListOf()) + } PinnedMessagesBannerItemsEffect( isFeatureEnabled = isFeatureEnabled, @@ -72,7 +72,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( pinnedItems = newItems }, onTimelineFail = { hasTimelineFailed -> - timelineFailed = hasTimelineFailed + hasTimelineFailedToLoad = hasTimelineFailed } ) @@ -90,7 +90,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( return pinnedMessagesBannerState( isFeatureEnabled = isFeatureEnabled, - hasTimelineFailed = timelineFailed, + hasTimelineFailed = hasTimelineFailedToLoad, realPinnedMessagesCount = knownPinnedMessagesCount, pinnedItems = pinnedItems, currentPinnedMessageIndex = currentPinnedMessageIndex, @@ -117,7 +117,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( PinnedMessagesBannerState.Loaded( currentPinnedMessage = currentPinnedMessage, currentPinnedMessageIndex = currentPinnedMessageIndex, - knownPinnedMessagesCount = realPinnedMessagesCount, + knownPinnedMessagesCount = pinnedItems.size, eventSink = eventSink ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index baab17577d..33e1b74aba 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -17,13 +17,23 @@ package io.element.android.features.messages.impl.pinned.banner import com.google.common.truth.Truth.assertThat +import io.element.android.features.networkmonitor.api.NetworkMonitor +import io.element.android.features.networkmonitor.test.FakeNetworkMonitor import io.element.android.libraries.eventformatter.test.FakePinnedMessagesBannerFormatter import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.AN_EVENT_ID_2 import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.matrix.test.room.aRoomInfo +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 import io.element.android.tests.testutils.test import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test @@ -31,23 +41,146 @@ import org.junit.Test class PinnedMessagesBannerPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = createPinnedMessagesBannerPresenter() + val presenter = createPinnedMessagesBannerPresenter(isFeatureEnabled = true) presenter.test { val initialState = awaitItem() - assertThat(initialState.pinnedMessagesCount).isEqualTo(0) - assertThat(initialState.currentPinnedMessageIndex).isEqualTo(0) - assertThat(initialState.currentPinnedMessage).isNull() + assertThat(initialState).isEqualTo(PinnedMessagesBannerState.Hidden) + cancelAndIgnoreRemainingEvents() } } @Test - fun `present - move to next pinned message when there is no pinned events`() = runTest { - val presenter = createPinnedMessagesBannerPresenter() + fun `present - feature disabled`() = runTest { + val presenter = createPinnedMessagesBannerPresenter(isFeatureEnabled = false) presenter.test { val initialState = awaitItem() - initialState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) - // Nothing is emitted - ensureAllEventsConsumed() + assertThat(initialState).isEqualTo(PinnedMessagesBannerState.Hidden) + } + } + + @Test + fun `present - loading state`() = runTest { + val room = FakeMatrixRoom( + pinnedEventsTimelineResult = { Result.success(FakeTimeline()) } + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) + } + val presenter = createPinnedMessagesBannerPresenter(room = room) + presenter.test { + skipItems(1) + val loadingState = awaitItem() + assertThat(loadingState).isEqualTo(PinnedMessagesBannerState.Loading(1)) + assertThat(loadingState.pinnedMessagesCount()).isEqualTo(1) + assertThat(loadingState.currentPinnedMessageIndex()).isEqualTo(0) + } + } + + @Test + fun `present - loaded state`() = runTest { + val messageContent = aMessageContent("A message") + val pinnedEventsTimeline = FakeTimeline( + timelineItems = flowOf( + listOf( + MatrixTimelineItem.Event( + uniqueId = "FAKE_UNIQUE_ID", + event = anEventTimelineItem( + eventId = AN_EVENT_ID, + content = messageContent, + ), + ) + ) + ) + ) + val room = FakeMatrixRoom( + pinnedEventsTimelineResult = { Result.success(pinnedEventsTimeline) } + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID, AN_EVENT_ID_2))) + } + val presenter = createPinnedMessagesBannerPresenter(room = room) + presenter.test { + skipItems(2) + val loadedState = awaitItem() as PinnedMessagesBannerState.Loaded + assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0) + assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(1) + assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent.toString()) + } + } + + @Test + fun `present - loaded state - multiple pinned messages`() = runTest { + val messageContent1 = aMessageContent("A message") + val messageContent2 = aMessageContent("Another message") + val pinnedEventsTimeline = FakeTimeline( + timelineItems = flowOf( + listOf( + MatrixTimelineItem.Event( + uniqueId = "FAKE_UNIQUE_ID", + event = anEventTimelineItem( + eventId = AN_EVENT_ID, + content = messageContent1, + ), + ), + MatrixTimelineItem.Event( + uniqueId = "FAKE_UNIQUE_ID_2", + event = anEventTimelineItem( + eventId = AN_EVENT_ID_2, + content = messageContent2, + ), + ) + ) + ) + ) + val room = FakeMatrixRoom( + pinnedEventsTimelineResult = { Result.success(pinnedEventsTimeline) } + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID, AN_EVENT_ID_2))) + } + val presenter = createPinnedMessagesBannerPresenter(room = room) + presenter.test { + skipItems(2) + awaitItem().also { loadedState -> + loadedState as PinnedMessagesBannerState.Loaded + assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0) + assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2) + assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent1.toString()) + loadedState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + } + + awaitItem().also { loadedState -> + loadedState as PinnedMessagesBannerState.Loaded + assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(1) + assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2) + assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent2.toString()) + loadedState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + } + + awaitItem().also { loadedState -> + loadedState as PinnedMessagesBannerState.Loaded + assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0) + assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2) + assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent1.toString()) + } + } + } + + @Test + fun `present - timeline failed`() = runTest { + val room = FakeMatrixRoom( + pinnedEventsTimelineResult = { Result.failure(Exception()) } + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) + } + val presenter = createPinnedMessagesBannerPresenter(room = room) + presenter.test { + skipItems(1) + awaitItem().also { loadingState -> + assertThat(loadingState).isEqualTo(PinnedMessagesBannerState.Loading(1)) + assertThat(loadingState.pinnedMessagesCount()).isEqualTo(1) + assertThat(loadingState.currentPinnedMessageIndex()).isEqualTo(0) + } + awaitItem().also { failedState -> + assertThat(failedState).isEqualTo(PinnedMessagesBannerState.Hidden) + } } } @@ -56,9 +189,10 @@ class PinnedMessagesBannerPresenterTest { itemFactory: PinnedMessagesBannerItemFactory = PinnedMessagesBannerItemFactory( coroutineDispatchers = testCoroutineDispatchers(), formatter = FakePinnedMessagesBannerFormatter( - formatLambda = { event -> "Content ${event.content}" } + formatLambda = { event -> "${event.content}" } ) ), + networkMonitor: NetworkMonitor = FakeNetworkMonitor(), isFeatureEnabled: Boolean = true, ): PinnedMessagesBannerPresenter { val featureFlagService = FakeFeatureFlagService( @@ -69,7 +203,8 @@ class PinnedMessagesBannerPresenterTest { return PinnedMessagesBannerPresenter( room = room, itemFactory = itemFactory, - featureFlagService = featureFlagService + featureFlagService = featureFlagService, + networkMonitor = networkMonitor, ) } } From d7edc7e165be01cfcdd995c5c5d904d613197160 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 6 Aug 2024 16:51:53 +0200 Subject: [PATCH 067/186] Pinned events : fix click on banner --- .../impl/pinned/banner/PinnedMessagesBannerView.kt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index b7524e43df..34b531ff55 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -82,15 +82,14 @@ fun PinnedMessagesBannerView( ) } is PinnedMessagesBannerState.Loaded -> { - fun onClick() { - onClick(state.currentPinnedMessage.eventId) - state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) - } - PinnedMessagesBannerRow( state = state, onViewAllClick = onViewAllClick, - modifier = Modifier.clickable(onClick = ::onClick), + modifier = Modifier.clickable( + onClick = { + onClick(state.currentPinnedMessage.eventId) + state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + }), ) } } From 5d2abd035081274e5351f042967294b2e90215cc Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 2 Aug 2024 17:44:04 +0200 Subject: [PATCH 068/186] timeline : allow rendering m.room.pinned_events --- .../android/appconfig/TimelineConfig.kt | 1 - gradle/libs.versions.toml | 2 +- .../impl/StateContentFormatter.kt | 31 ++++++++++++++++--- .../DefaultRoomLastMessageFormatterTest.kt | 2 +- .../api/timeline/item/event/OtherState.kt | 9 +++++- .../item/event/TimelineEventContentMapper.kt | 11 ++++++- 6 files changed, 46 insertions(+), 10 deletions(-) diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/TimelineConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/TimelineConfig.kt index 2ad2916550..2bbb96cabb 100644 --- a/appconfig/src/main/kotlin/io/element/android/appconfig/TimelineConfig.kt +++ b/appconfig/src/main/kotlin/io/element/android/appconfig/TimelineConfig.kt @@ -31,7 +31,6 @@ object TimelineConfig { StateEventType.ROOM_GUEST_ACCESS, StateEventType.ROOM_HISTORY_VISIBILITY, StateEventType.ROOM_JOIN_RULES, - StateEventType.ROOM_PINNED_EVENTS, StateEventType.ROOM_POWER_LEVELS, StateEventType.ROOM_SERVER_ACL, StateEventType.ROOM_TOMBSTONE, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d04849d390..686f3b5b20 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.35" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.37" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt index 164f54f911..09cb6ef2ce 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt @@ -80,11 +80,13 @@ class StateContentFormatter @Inject constructor( else -> sp.getString(R.string.state_event_room_topic_removed, senderDisambiguatedDisplayName) } } - OtherState.RoomPinnedEvents -> { - when { - //TODO manage all cases when available - senderIsYou -> sp.getString(R.string.state_event_room_pinned_events_changed_by_you) - else -> sp.getString(R.string.state_event_room_pinned_events_changed, senderDisambiguatedDisplayName) + is OtherState.RoomPinnedEvents -> when (renderingMode) { + RenderingMode.RoomList -> { + Timber.v("Filtering timeline item for room state change: $content") + null + } + RenderingMode.Timeline -> { + formatRoomPinnedEvents(content, senderIsYou, senderDisambiguatedDisplayName) } } is OtherState.Custom -> when (renderingMode) { @@ -215,4 +217,23 @@ class StateContentFormatter @Inject constructor( } } } + + private fun formatRoomPinnedEvents( + content: OtherState.RoomPinnedEvents, + senderIsYou: Boolean, + senderDisambiguatedDisplayName: String + ) = when (content.change) { + OtherState.RoomPinnedEvents.Change.ADDED -> when { + senderIsYou -> sp.getString(R.string.state_event_room_pinned_events_pinned_by_you) + else -> sp.getString(R.string.state_event_room_pinned_events_pinned, senderDisambiguatedDisplayName) + } + OtherState.RoomPinnedEvents.Change.REMOVED -> when { + senderIsYou -> sp.getString(R.string.state_event_room_pinned_events_unpinned_by_you) + else -> sp.getString(R.string.state_event_room_pinned_events_unpinned, senderDisambiguatedDisplayName) + } + OtherState.RoomPinnedEvents.Change.CHANGED -> when { + senderIsYou -> sp.getString(R.string.state_event_room_pinned_events_changed_by_you) + else -> sp.getString(R.string.state_event_room_pinned_events_changed, senderDisambiguatedDisplayName) + } + } } diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt index 5465882479..3f742c0954 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt @@ -660,7 +660,7 @@ class DefaultRoomLastMessageFormatterTest { OtherState.RoomGuestAccess, OtherState.RoomHistoryVisibility, OtherState.RoomJoinRules, - OtherState.RoomPinnedEvents, + OtherState.RoomPinnedEvents(OtherState.RoomPinnedEvents.Change.CHANGED), OtherState.RoomUserPowerLevels(emptyMap()), OtherState.RoomServerAcl, OtherState.RoomTombstone, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/OtherState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/OtherState.kt index d963b71a63..c046f6b2ae 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/OtherState.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/OtherState.kt @@ -32,7 +32,14 @@ sealed interface OtherState { data object RoomHistoryVisibility : OtherState data object RoomJoinRules : OtherState data class RoomName(val name: String?) : OtherState - data object RoomPinnedEvents : OtherState + data class RoomPinnedEvents(val change: Change) : OtherState { + enum class Change { + ADDED, + REMOVED, + CHANGED + } + } + data class RoomUserPowerLevels(val users: Map) : OtherState data object RoomServerAcl : OtherState data class RoomThirdPartyInvite(val displayName: String?) : OtherState diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt index 6b0da71eee..6e44579d7c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt @@ -40,6 +40,7 @@ import kotlinx.collections.immutable.toImmutableMap import org.matrix.rustcomponents.sdk.TimelineItemContent import org.matrix.rustcomponents.sdk.TimelineItemContentKind import org.matrix.rustcomponents.sdk.use +import uniffi.matrix_sdk_ui.RoomPinnedEventsChange import org.matrix.rustcomponents.sdk.EncryptedMessage as RustEncryptedMessage import org.matrix.rustcomponents.sdk.MembershipChange as RustMembershipChange import org.matrix.rustcomponents.sdk.OtherState as RustOtherState @@ -176,7 +177,7 @@ private fun RustOtherState.map(): OtherState { RustOtherState.RoomHistoryVisibility -> OtherState.RoomHistoryVisibility RustOtherState.RoomJoinRules -> OtherState.RoomJoinRules is RustOtherState.RoomName -> OtherState.RoomName(name) - RustOtherState.RoomPinnedEvents -> OtherState.RoomPinnedEvents + is RustOtherState.RoomPinnedEvents -> OtherState.RoomPinnedEvents(change.map()) is RustOtherState.RoomPowerLevels -> OtherState.RoomUserPowerLevels(users) RustOtherState.RoomServerAcl -> OtherState.RoomServerAcl is RustOtherState.RoomThirdPartyInvite -> OtherState.RoomThirdPartyInvite(displayName) @@ -187,6 +188,14 @@ private fun RustOtherState.map(): OtherState { } } +private fun RoomPinnedEventsChange.map(): OtherState.RoomPinnedEvents.Change { + return when (this) { + RoomPinnedEventsChange.ADDED -> OtherState.RoomPinnedEvents.Change.ADDED + RoomPinnedEventsChange.REMOVED -> OtherState.RoomPinnedEvents.Change.REMOVED + RoomPinnedEventsChange.CHANGED -> OtherState.RoomPinnedEvents.Change.CHANGED + } +} + private fun RustEncryptedMessage.map(): UnableToDecryptContent.Data { return when (this) { is RustEncryptedMessage.MegolmV1AesSha2 -> UnableToDecryptContent.Data.MegolmV1AesSha2(sessionId, cause.map()) From c609a7d002681854f6224f76c9059d6f3c740d12 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 6 Aug 2024 19:05:08 +0200 Subject: [PATCH 069/186] Pinned events : use correct ordering logic --- .../banner/PinnedMessagesBannerPresenter.kt | 12 ++++----- .../banner/PinnedMessagesBannerState.kt | 7 +++--- .../pinned/banner/PinnedMessagesBannerView.kt | 25 ++++++++----------- .../PinnedMessagesBannerPresenterTest.kt | 12 ++++----- 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index 6604114fc5..b04b6e656a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -53,10 +53,10 @@ class PinnedMessagesBannerPresenter @Inject constructor( override fun present(): PinnedMessagesBannerState { val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false) var hasTimelineFailedToLoad by rememberSaveable { mutableStateOf(false) } - var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(0) } + var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(-1) } val knownPinnedMessagesCount by remember { room.roomInfoFlow.map { roomInfo -> roomInfo.pinnedEventIds.size } - }.collectAsState(initial = null) + }.collectAsState(initial = 0) var pinnedItems by remember { mutableStateOf>(persistentListOf()) @@ -66,8 +66,8 @@ class PinnedMessagesBannerPresenter @Inject constructor( isFeatureEnabled = isFeatureEnabled, onItemsChange = { newItems -> val pinnedMessageCount = newItems.size - if (currentPinnedMessageIndex >= pinnedMessageCount) { - currentPinnedMessageIndex = 0 + if (currentPinnedMessageIndex >= pinnedMessageCount || currentPinnedMessageIndex < 0) { + currentPinnedMessageIndex = pinnedMessageCount - 1 } pinnedItems = newItems }, @@ -102,7 +102,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( private fun pinnedMessagesBannerState( isFeatureEnabled: Boolean, hasTimelineFailed: Boolean, - realPinnedMessagesCount: Int?, + realPinnedMessagesCount: Int, pinnedItems: ImmutableList, currentPinnedMessageIndex: Int, eventSink: (PinnedMessagesBannerEvents) -> Unit @@ -111,7 +111,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( return when { !isFeatureEnabled -> PinnedMessagesBannerState.Hidden hasTimelineFailed -> PinnedMessagesBannerState.Hidden - realPinnedMessagesCount == null || realPinnedMessagesCount == 0 -> PinnedMessagesBannerState.Hidden + realPinnedMessagesCount == 0 -> PinnedMessagesBannerState.Hidden currentPinnedMessage == null -> PinnedMessagesBannerState.Loading(realPinnedMessagesCount = realPinnedMessagesCount) else -> { PinnedMessagesBannerState.Loaded( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt index 886cef81de..c06003cc7c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt @@ -26,13 +26,14 @@ import io.element.android.libraries.ui.strings.CommonStrings @Immutable sealed interface PinnedMessagesBannerState { data object Hidden : PinnedMessagesBannerState - data class Loading(val realPinnedMessagesCount: Int) : PinnedMessagesBannerState + sealed interface Visible : PinnedMessagesBannerState + data class Loading(val realPinnedMessagesCount: Int) : Visible data class Loaded( val currentPinnedMessage: PinnedMessagesBannerItem, val currentPinnedMessageIndex: Int, val knownPinnedMessagesCount: Int, val eventSink: (PinnedMessagesBannerEvents) -> Unit - ) : PinnedMessagesBannerState + ) : Visible fun pinnedMessagesCount() = when (this) { is Hidden -> 0 @@ -42,7 +43,7 @@ sealed interface PinnedMessagesBannerState { fun currentPinnedMessageIndex() = when (this) { is Hidden -> 0 - is Loading -> 0 + is Loading -> realPinnedMessagesCount - 1 is Loaded -> currentPinnedMessageIndex } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index 34b531ff55..3a8fa448ef 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -74,22 +74,11 @@ fun PinnedMessagesBannerView( Box(modifier = modifier) { when (state) { PinnedMessagesBannerState.Hidden -> Unit - is PinnedMessagesBannerState.Loading -> { + is PinnedMessagesBannerState.Visible -> { PinnedMessagesBannerRow( state = state, + onClick = onClick, onViewAllClick = onViewAllClick, - modifier = Modifier.clickable(onClick = { }), - ) - } - is PinnedMessagesBannerState.Loaded -> { - PinnedMessagesBannerRow( - state = state, - onViewAllClick = onViewAllClick, - modifier = Modifier.clickable( - onClick = { - onClick(state.currentPinnedMessage.eventId) - state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) - }), ) } } @@ -99,6 +88,7 @@ fun PinnedMessagesBannerView( @Composable fun PinnedMessagesBannerRow( state: PinnedMessagesBannerState, + onClick: (EventId) -> Unit, onViewAllClick: () -> Unit, modifier: Modifier = Modifier, ) { @@ -108,7 +98,13 @@ fun PinnedMessagesBannerRow( .background(color = ElementTheme.colors.bgCanvasDefault) .fillMaxWidth() .drawBorder(borderColor) - .heightIn(min = 64.dp), + .heightIn(min = 64.dp) + .clickable { + if (state is PinnedMessagesBannerState.Loaded) { + onClick(state.currentPinnedMessage.eventId) + state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + } + }, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = spacedBy(10.dp) ) { @@ -202,7 +198,6 @@ private fun PinIndicators( state = lazyListState, verticalArrangement = spacedBy(2.dp), userScrollEnabled = false, - reverseLayout = true ) { items(pinsCount) { index -> Box( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index 33e1b74aba..6e78b2c446 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -140,25 +140,25 @@ class PinnedMessagesBannerPresenterTest { skipItems(2) awaitItem().also { loadedState -> loadedState as PinnedMessagesBannerState.Loaded - assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0) + assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(1) assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2) - assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent1.toString()) + assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent2.toString()) loadedState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) } awaitItem().also { loadedState -> loadedState as PinnedMessagesBannerState.Loaded - assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(1) + assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0) assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2) - assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent2.toString()) + assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent1.toString()) loadedState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) } awaitItem().also { loadedState -> loadedState as PinnedMessagesBannerState.Loaded - assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0) + assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(1) assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2) - assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent1.toString()) + assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent2.toString()) } } } From 63cc59a5c875c8a847076373ed809f58d0c7fec3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:35:37 +0200 Subject: [PATCH 070/186] Update dependency io.nlopez.compose.rules:detekt to v0.4.9 (#3277) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 87771dae05..d71f24b69f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -61,7 +61,7 @@ allprojects { config.from(files("$rootDir/tools/detekt/detekt.yml")) } dependencies { - detektPlugins("io.nlopez.compose.rules:detekt:0.4.8") + detektPlugins("io.nlopez.compose.rules:detekt:0.4.9") } // KtLint From 04995cb26cfe8e4aa3733de9381548d1701c287b Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 7 Aug 2024 12:26:52 +0200 Subject: [PATCH 071/186] Pinned events : add some ui testing --- .../features/messages/impl/MessagesView.kt | 5 +- .../impl/timeline/TimelinePresenter.kt | 2 + .../messages/impl/MessagesViewTest.kt | 26 ++++++ .../banner/PinnedMessagesBannerViewTest.kt | 87 +++++++++++++++++++ 4 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt 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 f365d917f0..df6aa26778 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 @@ -74,6 +74,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerView import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerViewDefaults +import io.element.android.features.messages.impl.timeline.FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS import io.element.android.features.messages.impl.timeline.TimelineEvents import io.element.android.features.messages.impl.timeline.TimelineView import io.element.android.features.messages.impl.timeline.components.JoinCallMenuItem @@ -401,13 +402,13 @@ private fun MessagesViewContent( nestedScrollConnection = scrollBehavior.nestedScrollConnection, ) AnimatedVisibility( - visible = state.pinnedMessagesBannerState != PinnedMessagesBannerState.Hidden && scrollBehavior.isVisible, + visible = state.pinnedMessagesBannerState is PinnedMessagesBannerState.Visible && scrollBehavior.isVisible, enter = expandVertically(), exit = shrinkVertically(), ) { fun focusOnPinnedEvent(eventId: EventId) { state.timelineState.eventSink( - TimelineEvents.FocusOnEvent(eventId = eventId, debounce = 200.milliseconds) + TimelineEvents.FocusOnEvent(eventId = eventId, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds) ) } PinnedMessagesBannerView( 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 93667f3987..3f7db9607a 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 @@ -57,6 +57,8 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +const val FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS = 200L + class TimelinePresenter @AssistedInject constructor( private val timelineItemsFactory: TimelineItemsFactory, private val timelineItemIndexer: TimelineItemIndexer, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index c88d2ffa28..b304ad9178 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -33,6 +33,7 @@ import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput import androidx.compose.ui.test.swipeRight +import androidx.compose.ui.text.AnnotatedString import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.emojibasebindings.Emoji import io.element.android.emojibasebindings.EmojibaseCategory @@ -43,6 +44,10 @@ 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.attachments.Attachment import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState +import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerItem +import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState +import io.element.android.features.messages.impl.timeline.FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS +import io.element.android.features.messages.impl.timeline.TimelineEvents import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReadReceipts import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo @@ -54,6 +59,7 @@ import io.element.android.features.messages.impl.timeline.components.receipt.aRe import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureCalledOnceWithParam @@ -72,6 +78,7 @@ import org.junit.Test import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config +import kotlin.time.Duration.Companion.milliseconds @RunWith(AndroidJUnit4::class) class MessagesViewTest { @@ -458,6 +465,25 @@ class MessagesViewTest { customReactionStateEventsRecorder.assertSingle(CustomReactionEvents.DismissCustomReactionSheet) eventsRecorder.assertSingle(MessagesEvents.ToggleReaction(aUnicode, timelineItem.eventId!!)) } + + @Test + fun `clicking on pinned messages banner emits the expected Event`() { + val eventsRecorder = EventsRecorder() + val state = aMessagesState( + timelineState = aTimelineState(eventSink = eventsRecorder), + pinnedMessagesBannerState = aLoadedPinnedMessagesBannerState( + knownPinnedMessagesCount = 2, + currentPinnedMessageIndex = 0, + currentPinnedMessage = PinnedMessagesBannerItem( + eventId = AN_EVENT_ID, + formatted = AnnotatedString("This is a pinned message") + ), + ), + ) + rule.setMessagesView(state = state) + rule.onNodeWithText("This is a pinned message").performClick() + eventsRecorder.assertSingle(TimelineEvents.FocusOnEvent(AN_EVENT_ID, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds)) + } } private fun AndroidComposeTestRule.setMessagesView( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt new file mode 100644 index 0000000000..ed23bdfb84 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.pinned.banner + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onRoot +import androidx.compose.ui.test.performClick +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.tests.testutils.EnsureNeverCalled +import io.element.android.tests.testutils.EnsureNeverCalledWithParam +import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.clickOn +import io.element.android.tests.testutils.ensureCalledOnce +import io.element.android.tests.testutils.ensureCalledOnceWithParam +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TestRule +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class PinnedMessagesBannerViewTest { + @get:Rule val rule = createAndroidComposeRule() + + @Test + fun `clicking on the banner invoke expected callback`() { + val eventsRecorder = EventsRecorder() + val state = aLoadedPinnedMessagesBannerState( + eventSink = eventsRecorder + ) + val pinnedEventId = state.currentPinnedMessage.eventId + ensureCalledOnceWithParam(pinnedEventId) { callback -> + rule.setPinnedMessagesBannerView( + state = state, + onClick = callback + ) + rule.onRoot().performClick() + eventsRecorder.assertSingle(PinnedMessagesBannerEvents.MoveToNextPinned) + } + } + + @Test + fun `clicking on view all emit the expected event`() { + val eventsRecorder = EventsRecorder(expectEvents = true) + val state = aLoadedPinnedMessagesBannerState( + eventSink = eventsRecorder + ) + ensureCalledOnce { callback -> + rule.setPinnedMessagesBannerView( + state = state, + onViewAllClick = callback + ) + rule.clickOn(CommonStrings.screen_room_pinned_banner_view_all_button_title) + } + } +} + +private fun AndroidComposeTestRule.setPinnedMessagesBannerView( + state: PinnedMessagesBannerState, + onClick: (EventId) -> Unit = EnsureNeverCalledWithParam(), + onViewAllClick: () -> Unit = EnsureNeverCalled(), +) { + setContent { + PinnedMessagesBannerView( + state = state, + onClick = onClick, + onViewAllClick = onViewAllClick + ) + } +} From 56e7e1f95933cf7fc2596aa31c4dbcfff6d74886 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 11:54:04 +0000 Subject: [PATCH 072/186] Update dependency org.matrix.rustcomponents:sdk-android to v0.2.38 --- 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 5ee63d4f6c..ddbd01901e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.37" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.38" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From 49f4526338399aef361c4c53913c258d94e67956 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 7 Aug 2024 15:57:27 +0200 Subject: [PATCH 073/186] Pinned events : banner goes backward instead of forward --- .../impl/pinned/banner/PinnedMessagesBannerPresenter.kt | 6 +++--- gradle/libs.versions.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index b04b6e656a..ba094dfffe 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -79,10 +79,10 @@ class PinnedMessagesBannerPresenter @Inject constructor( fun handleEvent(event: PinnedMessagesBannerEvents) { when (event) { is PinnedMessagesBannerEvents.MoveToNextPinned -> { - if (currentPinnedMessageIndex < pinnedItems.size - 1) { - currentPinnedMessageIndex++ + if (currentPinnedMessageIndex > 0) { + currentPinnedMessageIndex-- } else { - currentPinnedMessageIndex = 0 + currentPinnedMessageIndex = pinnedItems.size - 1 } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 686f3b5b20..751bff685e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.37" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.38" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From ac14845797be1ad42926c1299200b579f841afbd Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 7 Aug 2024 16:31:23 +0200 Subject: [PATCH 074/186] Pinned events: fix public compose method. --- .../messages/impl/pinned/banner/PinnedMessagesBannerView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index 3a8fa448ef..e925220796 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -86,7 +86,7 @@ fun PinnedMessagesBannerView( } @Composable -fun PinnedMessagesBannerRow( +private fun PinnedMessagesBannerRow( state: PinnedMessagesBannerState, onClick: (EventId) -> Unit, onViewAllClick: () -> Unit, From c96539163da0a8f91a9e3063a53b97045752f49d Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 7 Aug 2024 14:41:27 +0000 Subject: [PATCH 075/186] Update screenshots --- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en.png | 3 +++ ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en.png | 3 +++ ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en.png | 3 +++ ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en.png | 3 +++ ...impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_6_en.png | 3 +++ ...impl.pinned.banner_PinnedMessagesBannerView_Night_7_en.png | 3 +++ ...impl.pinned.banner_PinnedMessagesBannerView_Night_8_en.png | 3 +++ ...impl.pinned.banner_PinnedMessagesBannerView_Night_9_en.png | 3 +++ ...s.messages.impl.typing_MessagesViewWithTyping_Day_0_en.png | 4 ++-- ...s.messages.impl.typing_MessagesViewWithTyping_Day_1_en.png | 4 ++-- ...s.messages.impl.typing_MessagesViewWithTyping_Day_2_en.png | 4 ++-- ...messages.impl.typing_MessagesViewWithTyping_Night_0_en.png | 4 ++-- ...messages.impl.typing_MessagesViewWithTyping_Night_1_en.png | 4 ++-- ...messages.impl.typing_MessagesViewWithTyping_Night_2_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_0_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_10_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_11_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_12_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_1_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_3_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_4_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_5_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_6_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_7_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_8_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_9_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_0_en.png | 4 ++-- .../features.messages.impl_MessagesView_Night_10_en.png | 4 ++-- .../features.messages.impl_MessagesView_Night_11_en.png | 4 ++-- .../features.messages.impl_MessagesView_Night_12_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_1_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_3_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_4_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_5_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_6_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_7_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_8_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_9_en.png | 4 ++-- 50 files changed, 108 insertions(+), 84 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png index 558c81c8b7..1b6fb4bab8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7114202a1de9860547c525c0dadc110ce9e2e198465218ac2c33cf65f2f0eaa2 -size 9496 +oid sha256:96a867cb12498cbdc97957bee07855dfaa13602baddaf933aff2b666ef4c7650 +size 3642 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png index 3d77277fec..98720535b6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e6b5fd9ecc2b01cc8a83f3fe8e34352de1792a82db85c396377a18246adad1a -size 12953 +oid sha256:d5b71d416128b5b4791cec79ed7cdf963574c8fa66b32844ec798f55ddf62f42 +size 7960 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png index cfd32bb09c..336a9a5ad1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14ca5901134299e801e204e280d731e7de4072f1d522b076eb41c5f806897ed2 -size 12905 +oid sha256:720d657356e7fff0d0994a11fb95152b896b9e1de04dd50023b85c4d72cde6af +size 11414 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png index 40ed099f5b..558c81c8b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb206284c642dd665290d5d553491e622b8e15a64df7bb2dbd91ea5d3a13e19a -size 13041 +oid sha256:7114202a1de9860547c525c0dadc110ce9e2e198465218ac2c33cf65f2f0eaa2 +size 9496 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png index 15a58d4763..3d77277fec 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1940c4ee1e07c6a0198682460af1a6558fcaf14cb69ff061831cb591eb7aec3 -size 13066 +oid sha256:8e6b5fd9ecc2b01cc8a83f3fe8e34352de1792a82db85c396377a18246adad1a +size 12953 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png index ac3fb40ad1..575d07a9f1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fee5c1dbcdf7929f4762b2915584fe45b7f39916a949663f03e8d7e85e991b4b -size 12988 +oid sha256:743c950b885f3831034dab99571e19660a608eb8cc93218c939b570c1925e8f7 +size 12926 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en.png new file mode 100644 index 0000000000..cfd32bb09c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14ca5901134299e801e204e280d731e7de4072f1d522b076eb41c5f806897ed2 +size 12905 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en.png new file mode 100644 index 0000000000..40ed099f5b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb206284c642dd665290d5d553491e622b8e15a64df7bb2dbd91ea5d3a13e19a +size 13041 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en.png new file mode 100644 index 0000000000..15a58d4763 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1940c4ee1e07c6a0198682460af1a6558fcaf14cb69ff061831cb591eb7aec3 +size 13066 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en.png new file mode 100644 index 0000000000..ac3fb40ad1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fee5c1dbcdf7929f4762b2915584fe45b7f39916a949663f03e8d7e85e991b4b +size 12988 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png index 625e940b9e..d6fd8eeb70 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16658495b889654f152ba80a52111164f9682009b96abf1f3f20e660bd7c2407 -size 9297 +oid sha256:5bb36ccd718f3fec5b04f1bc812dc7718b5ea7fa4619c8b031466297a8d016fd +size 3659 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png index 3de9e45d12..7c8404b2d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43651c4a7f10406f1a6a4b995467ba292d4a43bc198dcf352ae2e66694154de2 -size 12340 +oid sha256:ff5e3562e981f2675a78e1cdf6cb7599471ad91030059fc8ff429165e1178131 +size 7873 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png index b320ff09e6..a45ab0dc23 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cca8ebb1ec12497de7e2efc1725a2e4427eecd1d340ae8176d10f914def0af25 -size 12297 +oid sha256:86caf295341ae9f5ae5cf99b39539a31afb0286c213e20b528078fc3fb3532e0 +size 10874 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png index 8299ed3a1c..625e940b9e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37bf00fbf548b7ba3d601af1ca489e07e25059c2f5a68abf9b85f4c656cf482c -size 12425 +oid sha256:16658495b889654f152ba80a52111164f9682009b96abf1f3f20e660bd7c2407 +size 9297 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png index 533f421f11..3de9e45d12 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed813a7003eb01a06667b10191990ed5bb3f75ee6a447cc4d52510b7e13b3724 -size 12448 +oid sha256:43651c4a7f10406f1a6a4b995467ba292d4a43bc198dcf352ae2e66694154de2 +size 12340 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png index a3b1d03bce..743791eeaa 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fa556ff7f6757c69c24e47520e08ccfd1b009d8e49a704c36d7fc4ca4186cbf -size 12378 +oid sha256:634006a41aee47e783bd8dcce295aa816f16e8d892f8967debeced863e4cc18b +size 12333 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en.png new file mode 100644 index 0000000000..b320ff09e6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cca8ebb1ec12497de7e2efc1725a2e4427eecd1d340ae8176d10f914def0af25 +size 12297 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en.png new file mode 100644 index 0000000000..8299ed3a1c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37bf00fbf548b7ba3d601af1ca489e07e25059c2f5a68abf9b85f4c656cf482c +size 12425 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en.png new file mode 100644 index 0000000000..533f421f11 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed813a7003eb01a06667b10191990ed5bb3f75ee6a447cc4d52510b7e13b3724 +size 12448 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en.png new file mode 100644 index 0000000000..a3b1d03bce --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6fa556ff7f6757c69c24e47520e08ccfd1b009d8e49a704c36d7fc4ca4186cbf +size 12378 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_0_en.png index 309c2bd605..0cb73c33e9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40960e8da93791449132dcc4c77a0ee4ca711358ea8f184c080bb4dddbe01724 -size 53669 +oid sha256:5c96744ce341811ece23e037fe15bdeeb48c7c6d9a0e931fec1bbd9993679aed +size 56230 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_1_en.png index 97450096ad..9f9598a575 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3505a9a29ca2636dbf201b1bdfb0a52d05ec885b5b14709dca3f3d1184cf258 -size 54547 +oid sha256:bb81645a873e815d96ec14efe0f84a2ff354093e62fb4957878bfc6ae214b9b8 +size 57067 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_2_en.png index 106395dcc2..a615304e7f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c495a8d5d9d4cef2f258d39decc7c841b2bee5196a330944e745d78af42b046c -size 50595 +oid sha256:4886e89da091d3869bfedb4e6f50009976fcab59f9617b8a4083c00e7027459a +size 53118 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_0_en.png index fdd5741b35..fa8b564c04 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43e55acf964c3bde105c3b00eaa9d67d9cdeb3334f0d641d18c5c2476a178655 -size 54416 +oid sha256:bc69aaab31d3f7e63b0481818b0c91c90aef44afc21ee06591ba69cdf45b978a +size 56712 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_1_en.png index 0e7b362a1c..c0d8ccb194 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1c749a0dff6fa96383268514cc330e02d13c1f50e5e6d238539c612cad7ba54d -size 55283 +oid sha256:0123a32464a8ca8ca3f85af8bfde18aca054c63e91ec1264a54e0177c58f0d4b +size 57539 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_2_en.png index 9f47f82ec1..5d5d4daf56 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.typing_MessagesViewWithTyping_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d741537e51e539a627aaee9a567a52a5a96207c8dfb7d69ce799438179ad6c29 -size 51388 +oid sha256:d5b8ff0e7e06516a29694c46cd22c5f09f029725cc3556c92a4491c00868151f +size 53662 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png index fb3f6bcbad..315f5a6852 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff311eba5365bb2a726eb59b71ecc40295032003dd5e03587efed086bdca79ec -size 55228 +oid sha256:277463b454876b3bff870e27deafd2b1d7affcdb5b72efcbb33bc4bfeac0a961 +size 56838 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 index 3b7df7988e..8707889672 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a24bfa8d881fac3d302898f7721c202c4cdedb37d4a75277cdc551a3a4e6ab80 -size 56882 +oid sha256:50517ad2782539a02ad2ac302e15da20f70e48f7b3ceab9438f41f4cb590d35a +size 58414 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 8fdd7ef2a3..c1ff22b537 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:6bca01015488a95b5a7daf277fe2e8114012e26ddacad195ddffba6c30edb080 -size 47104 +oid sha256:d5f6843d5976f1b476f36a01e6db8cce729862a5d138f23b2053f4a2f085d6df +size 48527 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 index 5f698df606..2d5a682ca0 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2b13b08c823c492457daf9b54ae17616845154af22a58880cd1081ab38b304c -size 55264 +oid sha256:3f2e8218de84709a8f42a9b4594c92da51a0427651de3c85885e8f147527bad9 +size 56860 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_1_en.png index c50c0cac8b..aa177b86a8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8424c63cd12ce518c096d62c8aeeffc5d7f7308fed1c1612dca7ad8e832606c4 -size 54790 +oid sha256:26490a489101d7718b08a7a85982af6dc1458dd01a1b9491903278d66724d0b6 +size 55998 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png index 6f7fa71e13..670b6e71d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8292a8b339592e3caf7118a16584ca41754900f03a8fa89bbc2424d2c3a6c9f1 -size 57701 +oid sha256:b3d185905f72389bd4edbed4d2ec7b6f4547465004174a1c798e604e83f84363 +size 59845 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png index ff5fb09de4..d8eb4d59a7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21f6c7ac3951f1aca51d6a2eabca7fdbdb1e00b3b3a3c44c96dae180bbee3623 -size 53216 +oid sha256:60cb1e0ab614fd719991e6c27ffdec3f68b6d9c6a7e0c5a8294eab3e4e51fa89 +size 54618 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png index 50322c59cf..3fca9380fb 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6db28acda62e4343ba7b4f64f31070253fe968f6ed8464afb1bb54506353278 -size 53081 +oid sha256:28615c037c99b201dd987faa83b4d184b7c593d0f3871c8f731d681ee6795a1d +size 54688 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_6_en.png index 69801a6993..850098bf34 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:806695481b7fe30e0c315b2e46c6fe48c21a1cedbfaf21736ad2716a41212473 -size 53645 +oid sha256:b6c85d42e90ea4c60d2cd4e0ac96fc38cb45504e1d863a4283f157f23e790899 +size 54346 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png index 45e3b40177..ac7ade1342 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c46f2842388c3d2d14cddae957ccc74c4a108faceff36846f5ca7daa00b9f593 -size 56398 +oid sha256:e5cbd166edeaec6ab06a5da87a0a023adfbb6f2e9727b4471c5586a2b897dbab +size 57729 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png index fe804c04af..176a8a9941 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e85f80a115c90586f81127b87aa5874a2f811d15c6af443bc0f0d7078c85f4e -size 38280 +oid sha256:8170faa5461e703c09803966cb25be7da37cbad08d6c8e21584c75eccf8a7d29 +size 39873 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png index c344a1583e..04baf108ba 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9ae1d25882c0c05723b68c61f97ac4ff2423750913f1f3186a6dad48e845e8e -size 37557 +oid sha256:1362fddcca30b31f92575d3e8020b4dc1c415ed0afefe29c56d5f2179d6a35f1 +size 39043 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png index ae3271ee83..becc913996 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e1974d0ec89208a55b0faeb230c89fc3ed10c1d4bead234dc39c06169ab24ca -size 55060 +oid sha256:16afa707859ef41a8420eec52f3e7e2e2c0d2dcf4b438e068468dcaa77fd4200 +size 56547 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 index 439ce25005..2c0cfc57da 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74a2c962831b6468dbff878d6f55460a5cdbc3d06c7566cecfb89b7bcf049b18 -size 56600 +oid sha256:ce3e8d221e1a4c9557fabd5902dd507d3c9a6774c4185612b708ef80499e13d3 +size 58015 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 c74b552192..b5146ab82b 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:e468164817c0e6302c1f8cacecb24daed2fe65eb5453723186651dc7bc1851cf -size 43297 +oid sha256:4dbd737eaa65c834550ab421e4e3ee5c77701ab58ce06197048dbf8e044c548a +size 44487 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 index 7c09af645a..a39a656f25 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad336e1b96ac2528cd1d7573fda649e5fe09235b72d555d79f32cca4eb8c1c05 -size 55084 +oid sha256:0bdec5d25d991452633e77e4d5c2468d4b48cd880fbfb713a6c3b897cbdde921 +size 56587 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_1_en.png index b935cc06e7..08e5acbbc8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5b9fe533cfad8892708a609a79fa1f8bed95ad8fb20b979993da9b2d1ea380d -size 54511 +oid sha256:872853bf96c32e0f375d6ec772437e27e21d16506f7fa2f7853ef91cd274bb28 +size 55440 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png index 0cc32b0dbf..0e7a7f783c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4d0b4ab8e2234e08ca7c67d4653729abcf2c4ed055b983fdde15589daaf0124 -size 57234 +oid sha256:86a3e684d4a794915344963c4dd26e1e68729e7e5d9c4091c7824cf0901684b3 +size 59342 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png index b513f8b897..4776d19372 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4a32531adceea6b03b25291435fb2df753868571b3edf3ea29f00353d07087e -size 49544 +oid sha256:c446a2b24ae180496649f518f53f15f939c1e166093b82e479d2d7f1a8a7829d +size 50742 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png index bb7da5784e..70caedc0cf 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:534490ea60a6078200761864dd112f54be124647f818ccec77fb986ea71582a8 -size 52689 +oid sha256:3df1d346ea653cfafea9e2e13a7ff47017a480ce593d1c959553e7b8073f0250 +size 54217 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_6_en.png index 1eb51aad8a..6cc5a72d24 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2063163a5ac3c78398df388b9e471362a32244d5bdf4790409358640b5cfb15f -size 53399 +oid sha256:6dcf842a6bc3abfc9168b0e30354f3de2f72bddb04b203dcf9d211c77155bcfd +size 53901 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png index a8c890d748..bcc10ece2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d0d0b885ae157ff456d7113707bc72f3ced9ab74c895cdf7377adc1bc8c48db -size 52373 +oid sha256:8639bc9d5728e8bf5b1b3ab76aff16aacf89ff15397770f08c5211dc9342fa78 +size 53545 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png index ecdeb0c387..2d560199c1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:828b9893e06b168b16b42950f42b89ecc51b73c9b425732d379a72d737f04491 -size 36126 +oid sha256:310862ba0323270901b3a554ff230931a75de56a77487c7b0e63137f90cc0214 +size 37398 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png index 5920916813..df43160511 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f251ca0e5c4f98b7c5889b42161e4d52f3faf37850c242122aac2d124a1357b1 -size 35393 +oid sha256:5abde960f15c7d28e6fc538f5450f277e89ee17893e12daaba004ca7a0f09974 +size 36656 From a7afdcb5a0df147211d12be79e53e05629ad6eea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:50:30 +0000 Subject: [PATCH 076/186] Update dependency io.nlopez.compose.rules:detekt to v0.4.10 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index d71f24b69f..97daebb1d3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -61,7 +61,7 @@ allprojects { config.from(files("$rootDir/tools/detekt/detekt.yml")) } dependencies { - detektPlugins("io.nlopez.compose.rules:detekt:0.4.9") + detektPlugins("io.nlopez.compose.rules:detekt:0.4.10") } // KtLint From 331413e8b4f856921b0c07f37e92e3e9981e2751 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 7 Aug 2024 19:00:41 +0200 Subject: [PATCH 077/186] Pinned events: make sure state is preserved --- .../pinned/IsPinnedMessagesFeatureEnabled.kt | 54 +++++++++++++++++++ .../banner/PinnedMessagesBannerPresenter.kt | 44 ++++++++------- .../PinnedMessagesBannerPresenterTest.kt | 9 +--- 3 files changed, 76 insertions(+), 31 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/IsPinnedMessagesFeatureEnabled.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/IsPinnedMessagesFeatureEnabled.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/IsPinnedMessagesFeatureEnabled.kt new file mode 100644 index 0000000000..5ef5e2c793 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/IsPinnedMessagesFeatureEnabled.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.pinned + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import javax.inject.Inject + +fun interface IsPinnedMessagesFeatureEnabled { + @Composable + operator fun invoke(): Boolean +} + +@ContributesBinding(AppScope::class) +class DefaultIsPinnedMessagesFeatureEnabled @Inject constructor( + private val featureFlagService: FeatureFlagService, +) : IsPinnedMessagesFeatureEnabled { + @Composable + override operator fun invoke(): Boolean { + var isFeatureEnabled by rememberSaveable { + mutableStateOf(false) + } + LaunchedEffect(Unit) { + featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents) + .onEach { isFeatureEnabled = it } + .launchIn(this) + } + return isFeatureEnabled + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index ba094dfffe..578e38eaa9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -26,10 +26,9 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import io.element.android.features.messages.impl.pinned.IsPinnedMessagesFeatureEnabled import io.element.android.features.networkmonitor.api.NetworkMonitor 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.room.MatrixRoom import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -46,21 +45,20 @@ import kotlin.time.Duration.Companion.milliseconds class PinnedMessagesBannerPresenter @Inject constructor( private val room: MatrixRoom, private val itemFactory: PinnedMessagesBannerItemFactory, - private val featureFlagService: FeatureFlagService, + private val isFeatureEnabled: IsPinnedMessagesFeatureEnabled, private val networkMonitor: NetworkMonitor, ) : Presenter { + private val pinnedItems = mutableStateOf>(persistentListOf()) + @Composable override fun present(): PinnedMessagesBannerState { - val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false) - var hasTimelineFailedToLoad by rememberSaveable { mutableStateOf(false) } - var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(-1) } + val isFeatureEnabled = isFeatureEnabled() val knownPinnedMessagesCount by remember { room.roomInfoFlow.map { roomInfo -> roomInfo.pinnedEventIds.size } }.collectAsState(initial = 0) - var pinnedItems by remember { - mutableStateOf>(persistentListOf()) - } + var hasTimelineFailedToLoad by rememberSaveable { mutableStateOf(false) } + var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(-1) } PinnedMessagesBannerItemsEffect( isFeatureEnabled = isFeatureEnabled, @@ -69,7 +67,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( if (currentPinnedMessageIndex >= pinnedMessageCount || currentPinnedMessageIndex < 0) { currentPinnedMessageIndex = pinnedMessageCount - 1 } - pinnedItems = newItems + pinnedItems.value = newItems }, onTimelineFail = { hasTimelineFailed -> hasTimelineFailedToLoad = hasTimelineFailed @@ -82,7 +80,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( if (currentPinnedMessageIndex > 0) { currentPinnedMessageIndex-- } else { - currentPinnedMessageIndex = pinnedItems.size - 1 + currentPinnedMessageIndex = pinnedItems.value.size - 1 } } } @@ -92,7 +90,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( isFeatureEnabled = isFeatureEnabled, hasTimelineFailed = hasTimelineFailedToLoad, realPinnedMessagesCount = knownPinnedMessagesCount, - pinnedItems = pinnedItems, + pinnedItems = pinnedItems.value, currentPinnedMessageIndex = currentPinnedMessageIndex, eventSink = ::handleEvent ) @@ -111,16 +109,14 @@ class PinnedMessagesBannerPresenter @Inject constructor( return when { !isFeatureEnabled -> PinnedMessagesBannerState.Hidden hasTimelineFailed -> PinnedMessagesBannerState.Hidden + currentPinnedMessage != null -> PinnedMessagesBannerState.Loaded( + currentPinnedMessage = currentPinnedMessage, + currentPinnedMessageIndex = currentPinnedMessageIndex, + knownPinnedMessagesCount = pinnedItems.size, + eventSink = eventSink + ) realPinnedMessagesCount == 0 -> PinnedMessagesBannerState.Hidden - currentPinnedMessage == null -> PinnedMessagesBannerState.Loading(realPinnedMessagesCount = realPinnedMessagesCount) - else -> { - PinnedMessagesBannerState.Loaded( - currentPinnedMessage = currentPinnedMessage, - currentPinnedMessageIndex = currentPinnedMessageIndex, - knownPinnedMessagesCount = pinnedItems.size, - eventSink = eventSink - ) - } + else -> PinnedMessagesBannerState.Loading(realPinnedMessagesCount = realPinnedMessagesCount) } } @@ -136,8 +132,10 @@ class PinnedMessagesBannerPresenter @Inject constructor( val networkStatus by networkMonitor.connectivity.collectAsState() LaunchedEffect(isFeatureEnabled, networkStatus) { - if (!isFeatureEnabled) return@LaunchedEffect - + if (!isFeatureEnabled) { + updatedOnItemsChange(persistentListOf()) + return@LaunchedEffect + } val pinnedEventsTimeline = room.pinnedEventsTimeline() .onFailure { updatedOnTimelineFail(true) } .onSuccess { updatedOnTimelineFail(false) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index 6e78b2c446..fbbf40b7f0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -20,8 +20,6 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.test.FakeNetworkMonitor import io.element.android.libraries.eventformatter.test.FakePinnedMessagesBannerFormatter -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.test.AN_EVENT_ID @@ -195,15 +193,10 @@ class PinnedMessagesBannerPresenterTest { networkMonitor: NetworkMonitor = FakeNetworkMonitor(), isFeatureEnabled: Boolean = true, ): PinnedMessagesBannerPresenter { - val featureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.PinnedEvents.key to isFeatureEnabled - ) - ) return PinnedMessagesBannerPresenter( room = room, itemFactory = itemFactory, - featureFlagService = featureFlagService, + isFeatureEnabled = { isFeatureEnabled }, networkMonitor = networkMonitor, ) } From 896b702cdf88b10507daeb7ead7c905ee3f8a2f2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 09:17:28 +0000 Subject: [PATCH 078/186] Update dependency androidx.annotation:annotation-jvm to v1.8.2 (#3282) 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 ddbd01901e..33d1462028 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -75,7 +75,7 @@ oss_licenses_plugin = "com.google.android.gms:oss-licenses-plugin:0.10.6" # AndroidX androidx_core = { module = "androidx.core:core", version.ref = "core" } androidx_corektx = { module = "androidx.core:core-ktx", version.ref = "core" } -androidx_annotationjvm = "androidx.annotation:annotation-jvm:1.8.1" +androidx_annotationjvm = "androidx.annotation:annotation-jvm:1.8.2" androidx_datastore_preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" } androidx_datastore_datastore = { module = "androidx.datastore:datastore", version.ref = "datastore" } androidx_exifinterface = "androidx.exifinterface:exifinterface:1.3.7" From e6ba45d904ab7fb37e50cf76ad90f8e86d46b177 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 14:35:53 +0200 Subject: [PATCH 079/186] Update kotlin (#2990) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update kotlin and related dependencies * Reset back Kotlinx serialization to `v1.6.3` since we can't use `1.7.x` until we upgrade to Kotlin 2.0 --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- gradle/libs.versions.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 33d1462028..36888ad06b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,8 +4,8 @@ [versions] # Project android_gradle_plugin = "8.4.1" -kotlin = "1.9.24" -ksp = "1.9.24-1.0.20" +kotlin = "1.9.25" +ksp = "1.9.25-1.0.20" firebaseAppDistribution = "5.0.0" # AndroidX @@ -25,7 +25,7 @@ camera = "1.3.4" # Compose compose_bom = "2024.06.00" -composecompiler = "1.5.14" +composecompiler = "1.5.15" # Coroutines coroutines = "1.8.1" @@ -56,7 +56,7 @@ autoservice = "1.1.1" # quality androidx-test-ext-junit = "1.2.1" -kover = "0.8.0" +kover = "0.8.3" [libraries] # Project From a5d633a02f33f3439089d2da05ecb88c6413f0e7 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 8 Aug 2024 14:51:49 +0200 Subject: [PATCH 080/186] Pinned events : minor code quality changes --- .../banner/PinnedMessagesBannerPresenter.kt | 18 +++++++----------- .../pinned/banner/PinnedMessagesBannerState.kt | 10 +++++----- .../PinnedMessagesBannerStateProvider.kt | 4 ++-- .../PinnedMessagesBannerPresenterTest.kt | 8 ++++---- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index 578e38eaa9..13c45e0092 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -53,7 +53,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( @Composable override fun present(): PinnedMessagesBannerState { val isFeatureEnabled = isFeatureEnabled() - val knownPinnedMessagesCount by remember { + val expectedPinnedMessagesCount by remember { room.roomInfoFlow.map { roomInfo -> roomInfo.pinnedEventIds.size } }.collectAsState(initial = 0) @@ -77,11 +77,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( fun handleEvent(event: PinnedMessagesBannerEvents) { when (event) { is PinnedMessagesBannerEvents.MoveToNextPinned -> { - if (currentPinnedMessageIndex > 0) { - currentPinnedMessageIndex-- - } else { - currentPinnedMessageIndex = pinnedItems.value.size - 1 - } + currentPinnedMessageIndex = (currentPinnedMessageIndex - 1).mod(pinnedItems.value.size) } } } @@ -89,7 +85,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( return pinnedMessagesBannerState( isFeatureEnabled = isFeatureEnabled, hasTimelineFailed = hasTimelineFailedToLoad, - realPinnedMessagesCount = knownPinnedMessagesCount, + expectedPinnedMessagesCount = expectedPinnedMessagesCount, pinnedItems = pinnedItems.value, currentPinnedMessageIndex = currentPinnedMessageIndex, eventSink = ::handleEvent @@ -100,7 +96,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( private fun pinnedMessagesBannerState( isFeatureEnabled: Boolean, hasTimelineFailed: Boolean, - realPinnedMessagesCount: Int, + expectedPinnedMessagesCount: Int, pinnedItems: ImmutableList, currentPinnedMessageIndex: Int, eventSink: (PinnedMessagesBannerEvents) -> Unit @@ -112,11 +108,11 @@ class PinnedMessagesBannerPresenter @Inject constructor( currentPinnedMessage != null -> PinnedMessagesBannerState.Loaded( currentPinnedMessage = currentPinnedMessage, currentPinnedMessageIndex = currentPinnedMessageIndex, - knownPinnedMessagesCount = pinnedItems.size, + loadedPinnedMessagesCount = pinnedItems.size, eventSink = eventSink ) - realPinnedMessagesCount == 0 -> PinnedMessagesBannerState.Hidden - else -> PinnedMessagesBannerState.Loading(realPinnedMessagesCount = realPinnedMessagesCount) + expectedPinnedMessagesCount == 0 -> PinnedMessagesBannerState.Hidden + else -> PinnedMessagesBannerState.Loading(expectedPinnedMessagesCount = expectedPinnedMessagesCount) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt index c06003cc7c..a686ada33c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt @@ -27,23 +27,23 @@ import io.element.android.libraries.ui.strings.CommonStrings sealed interface PinnedMessagesBannerState { data object Hidden : PinnedMessagesBannerState sealed interface Visible : PinnedMessagesBannerState - data class Loading(val realPinnedMessagesCount: Int) : Visible + data class Loading(val expectedPinnedMessagesCount: Int) : Visible data class Loaded( val currentPinnedMessage: PinnedMessagesBannerItem, val currentPinnedMessageIndex: Int, - val knownPinnedMessagesCount: Int, + val loadedPinnedMessagesCount: Int, val eventSink: (PinnedMessagesBannerEvents) -> Unit ) : Visible fun pinnedMessagesCount() = when (this) { is Hidden -> 0 - is Loading -> realPinnedMessagesCount - is Loaded -> knownPinnedMessagesCount + is Loading -> expectedPinnedMessagesCount + is Loaded -> loadedPinnedMessagesCount } fun currentPinnedMessageIndex() = when (this) { is Hidden -> 0 - is Loading -> realPinnedMessagesCount - 1 + is Loading -> expectedPinnedMessagesCount - 1 is Loaded -> currentPinnedMessageIndex } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt index bdcab879fe..e9d0a27c16 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt @@ -42,7 +42,7 @@ internal fun aHiddenPinnedMessagesBannerState() = PinnedMessagesBannerState.Hidd internal fun aLoadingPinnedMessagesBannerState( knownPinnedMessagesCount: Int = 4 ) = PinnedMessagesBannerState.Loading( - realPinnedMessagesCount = knownPinnedMessagesCount + expectedPinnedMessagesCount = knownPinnedMessagesCount ) internal fun aLoadedPinnedMessagesBannerState( @@ -56,6 +56,6 @@ internal fun aLoadedPinnedMessagesBannerState( ) = PinnedMessagesBannerState.Loaded( currentPinnedMessage = currentPinnedMessage, currentPinnedMessageIndex = currentPinnedMessageIndex, - knownPinnedMessagesCount = knownPinnedMessagesCount, + loadedPinnedMessagesCount = knownPinnedMessagesCount, eventSink = eventSink ) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index fbbf40b7f0..1ae4729a40 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -99,7 +99,7 @@ class PinnedMessagesBannerPresenterTest { skipItems(2) val loadedState = awaitItem() as PinnedMessagesBannerState.Loaded assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0) - assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(1) + assertThat(loadedState.loadedPinnedMessagesCount).isEqualTo(1) assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent.toString()) } } @@ -139,7 +139,7 @@ class PinnedMessagesBannerPresenterTest { awaitItem().also { loadedState -> loadedState as PinnedMessagesBannerState.Loaded assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(1) - assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2) + assertThat(loadedState.loadedPinnedMessagesCount).isEqualTo(2) assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent2.toString()) loadedState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) } @@ -147,7 +147,7 @@ class PinnedMessagesBannerPresenterTest { awaitItem().also { loadedState -> loadedState as PinnedMessagesBannerState.Loaded assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0) - assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2) + assertThat(loadedState.loadedPinnedMessagesCount).isEqualTo(2) assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent1.toString()) loadedState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) } @@ -155,7 +155,7 @@ class PinnedMessagesBannerPresenterTest { awaitItem().also { loadedState -> loadedState as PinnedMessagesBannerState.Loaded assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(1) - assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2) + assertThat(loadedState.loadedPinnedMessagesCount).isEqualTo(2) assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent2.toString()) } } From 2a79f05be03b8c9228cbb3f333846cf014aa71cf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 07:26:14 +0000 Subject: [PATCH 081/186] Update dependency com.posthog:posthog-android to v3.5.0 (#3287) 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 d5c36cba37..16e0dfd9e4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -186,7 +186,7 @@ zxing_cpp = "io.github.zxing-cpp:android:2.2.0" play_services_oss_licenses = "com.google.android.gms:play-services-oss-licenses:17.1.0" # Analytics -posthog = "com.posthog:posthog-android:3.4.2" +posthog = "com.posthog:posthog-android:3.5.0" sentry = "io.sentry:sentry-android:7.12.1" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.23.1" From abc43c1c968c35037965269760edd72b61e379ad Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 07:28:09 +0000 Subject: [PATCH 082/186] Update dependency io.sentry:sentry-android to v7.13.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 16e0dfd9e4..1eaca635a4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -187,7 +187,7 @@ play_services_oss_licenses = "com.google.android.gms:play-services-oss-licenses: # Analytics posthog = "com.posthog:posthog-android:3.5.0" -sentry = "io.sentry:sentry-android:7.12.1" +sentry = "io.sentry:sentry-android:7.13.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.23.1" From 0b8e88854025a8675d14448a827556afa73a8108 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 11:31:55 +0200 Subject: [PATCH 083/186] Update wysiwyg to v2.37.8 (#3284) 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 16e0dfd9e4..6378685636 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -44,7 +44,7 @@ serialization_json = "1.6.3" showkase = "1.0.3" appyx = "1.4.0" sqldelight = "2.0.2" -wysiwyg = "2.37.7" +wysiwyg = "2.37.8" telephoto = "0.12.1" # DI From 65718b3e960c3631f540b4b0f0a1ca9aa235f9b3 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 9 Aug 2024 12:42:15 +0200 Subject: [PATCH 084/186] Update the SDK bindings to `v0.2.39` (#3288) - Rework `RoomSyncSubscriber` to work with the new `RoomListService.subscribeToRooms` API. --- .idea/kotlinc.xml | 2 +- gradle/libs.versions.toml | 2 +- .../matrix/impl/room/RoomSyncSubscriber.kt | 43 +++++++++---------- .../roomlist/RoomSummaryListProcessorTest.kt | 4 +- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 148fdd2469..4cb7457249 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6378685636..712fa4139f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.38" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.39" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } 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 a52d3a87ed..b149f88006 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 @@ -51,23 +51,15 @@ class RoomSyncSubscriber( includeHeroes = false, ) - suspend fun subscribe(roomId: RoomId) = mutex.withLock { - withContext(dispatchers.io) { - try { - subscribeToRoom(roomId) - } catch (exception: Exception) { - Timber.e("Failed to subscribe to room $roomId") - } - } - } - - suspend fun batchSubscribe(roomIds: List) = mutex.withLock { - withContext(dispatchers.io) { - for (roomId in roomIds) { + suspend fun subscribe(roomId: RoomId) { + mutex.withLock { + withContext(dispatchers.io) { try { - subscribeToRoom(roomId) - } catch (cancellationException: CancellationException) { - throw cancellationException + if (!isSubscribedTo(roomId)) { + Timber.d("Subscribing to room $roomId}") + roomListService.subscribeToRooms(listOf(roomId.value), settings) + } + subscribedRoomIds.add(roomId) } catch (exception: Exception) { Timber.e("Failed to subscribe to room $roomId") } @@ -75,14 +67,21 @@ class RoomSyncSubscriber( } } - private fun subscribeToRoom(roomId: RoomId) { - if (!isSubscribedTo(roomId)) { - Timber.d("Subscribing to room $roomId}") - roomListService.room(roomId.value).use { roomListItem -> - roomListItem.subscribe(settings) + suspend fun batchSubscribe(roomIds: List) = mutex.withLock { + withContext(dispatchers.io) { + try { + val roomIdsToSubscribeTo = roomIds.filterNot { isSubscribedTo(it) } + if (roomIdsToSubscribeTo.isNotEmpty()) { + Timber.d("Subscribing to rooms: $roomIds") + roomListService.subscribeToRooms(roomIdsToSubscribeTo.map { it.value }, settings) + subscribedRoomIds.addAll(roomIds) + } + } catch (cancellationException: CancellationException) { + throw cancellationException + } catch (exception: Exception) { + Timber.e(exception, "Failed to subscribe to rooms: $roomIds") } } - subscribedRoomIds.add(roomId) } fun isSubscribedTo(roomId: RoomId): Boolean { 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 33d8a94bb5..abaae99397 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 @@ -189,6 +189,8 @@ class RoomSummaryListProcessorTest { override fun syncIndicator(delayBeforeShowingInMs: UInt, delayBeforeHidingInMs: UInt, listener: RoomListServiceSyncIndicatorListener): TaskHandle { return TaskHandle(Pointer.NULL) } + + override fun subscribeToRooms(roomIds: List, settings: RoomSubscription?) = Unit } } @@ -270,6 +272,4 @@ class FakeRoomListItem( override suspend fun latestEvent(): EventTimelineItem? { return latestEvent } - - override fun subscribe(settings: RoomSubscription?) = Unit } From b16edcb62ceee8afd418d864fe619107f773fa36 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 9 Aug 2024 15:02:50 +0200 Subject: [PATCH 085/186] Enable sync on push feature flag to partially sync when notifications arrive (#3290) --- .../element/android/libraries/featureflag/api/FeatureFlags.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 4d37576afc..ccc910d02c 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -131,7 +131,7 @@ enum class FeatureFlags( key = "feature.syncOnPush", title = "Sync on push", description = "Subscribe to room sync when a push is received", - defaultValue = { false }, + defaultValue = { true }, isFinished = false, ), } From 250f0706fb0201b72a3c14890e3fa720f817e49c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:03:14 +0200 Subject: [PATCH 086/186] Update gradle/actions action to v4 (#3265) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update gradle/actions action to v4 * Remove unnecessary gradle validation after action update to v4 --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- .github/workflows/build.yml | 2 +- .github/workflows/build_enterprise.yml | 2 +- .github/workflows/generate_github_pages.yml | 2 +- .github/workflows/gradle-wrapper-validation.yml | 15 --------------- .github/workflows/maestro.yml | 2 +- .github/workflows/nightlyReports.yml | 4 ++-- .github/workflows/quality.yml | 12 ++++++------ .github/workflows/recordScreenshots.yml | 2 +- .github/workflows/release.yml | 6 +++--- .github/workflows/sonar.yml | 2 +- .github/workflows/sync-localazy.yml | 2 +- .github/workflows/tests.yml | 2 +- 12 files changed, 19 insertions(+), 34 deletions(-) delete mode 100644 .github/workflows/gradle-wrapper-validation.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 92380492a2..9f039ce5b9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble debug Gplay APK diff --git a/.github/workflows/build_enterprise.yml b/.github/workflows/build_enterprise.yml index 602b43a7e1..737b61ee06 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -44,7 +44,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble debug Gplay Enterprise APK diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index 46494ba76a..c86c5799e3 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -19,7 +19,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml deleted file mode 100644 index 3c619328ae..0000000000 --- a/.github/workflows/gradle-wrapper-validation.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: "Validate Gradle Wrapper" -on: - pull_request: - merge_group: - push: - branches: [ main, develop ] - -jobs: - validation: - name: "Validation" - runs-on: ubuntu-latest - # No concurrency required, this is a prerequisite to other actions and should run every time. - steps: - - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v3 diff --git a/.github/workflows/maestro.yml b/.github/workflows/maestro.yml index eb39516e5e..fd2cc75fd0 100644 --- a/.github/workflows/maestro.yml +++ b/.github/workflows/maestro.yml @@ -39,7 +39,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble debug APK diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index 94f1ab275d..a0d39068eb 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -27,7 +27,7 @@ jobs: java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: false @@ -67,7 +67,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Dependency analysis diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index a0643c426f..5157a4b3d6 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -52,7 +52,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 @@ -90,7 +90,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run Konsist tests @@ -130,7 +130,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Build Gplay Debug @@ -174,7 +174,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run Detekt @@ -214,7 +214,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run Ktlint check @@ -254,7 +254,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run Knit diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml index 44522a0084..e176c5d7bc 100644 --- a/.github/workflows/recordScreenshots.yml +++ b/.github/workflows/recordScreenshots.yml @@ -39,7 +39,7 @@ jobs: java-version: '17' # Add gradle cache, this should speed up the process - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Record screenshots diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 38be804fc1..fea2b6715c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 - name: Create app bundle env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} @@ -61,7 +61,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 - name: Create Enterprise app bundle env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} @@ -89,7 +89,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 - name: Create APKs env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index bbab77cf65..b5e0be7e2d 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -33,7 +33,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Build Gplay Debug diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 5f99cac17a..1330b373bf 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -18,7 +18,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fa274baf89..e96dcae925 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -52,7 +52,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} From 738295a933c47b48fff844b8cedeb006c22fdc18 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:04:10 +0200 Subject: [PATCH 087/186] Update android.gradle.plugin to v8.5.2 (#3004) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update android.gradle.plugin * Fix release builds with AGP 8.5 by removing the minification config in each library module. I believe this is now centralised. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- app/proguard-rules.pro | 2 ++ gradle.properties | 3 --- gradle/libs.versions.toml | 2 +- libraries/designsystem/build.gradle.kts | 1 - libraries/encrypted-db/build.gradle.kts | 2 +- libraries/network/build.gradle.kts | 1 - libraries/pushproviders/firebase/build.gradle.kts | 1 - 7 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index c800b9d996..89dcab5fad 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -40,3 +40,5 @@ -keepclassmembers class android.view.JavaViewSpy { static int windowAttachCount(android.view.View); } + +-keep class io.element.android.x.di.** { *; } diff --git a/gradle.properties b/gradle.properties index b1f6468108..2d4c31a3aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -59,6 +59,3 @@ android.enableBuildConfigAsBytecode=true # By default, the plugin applies itself to all subprojects, but we don't want that as it would cause issues with builds using local AARs dependency.analysis.autoapply=false - -# Disable new R8 shrinking for local dependencies as it causes issues with release builds -android.disableMinifyLocalDependenciesForLibraries=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 712fa4139f..ead60dcde4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ [versions] # Project -android_gradle_plugin = "8.4.1" +android_gradle_plugin = "8.5.2" kotlin = "1.9.25" ksp = "1.9.25-1.0.20" firebaseAppDistribution = "5.0.0" diff --git a/libraries/designsystem/build.gradle.kts b/libraries/designsystem/build.gradle.kts index e737220961..81abc3127f 100644 --- a/libraries/designsystem/build.gradle.kts +++ b/libraries/designsystem/build.gradle.kts @@ -29,7 +29,6 @@ android { buildTypes { getByName("release") { - isMinifyEnabled = true consumerProguardFiles("consumer-rules.pro") } } diff --git a/libraries/encrypted-db/build.gradle.kts b/libraries/encrypted-db/build.gradle.kts index 40db7f7fde..f64e22875e 100644 --- a/libraries/encrypted-db/build.gradle.kts +++ b/libraries/encrypted-db/build.gradle.kts @@ -22,7 +22,7 @@ android { buildTypes { release { - isMinifyEnabled = true + isMinifyEnabled = false consumerProguardFiles("consumer-proguard-rules.pro") } } diff --git a/libraries/network/build.gradle.kts b/libraries/network/build.gradle.kts index 2b18f1e37a..36294f4c08 100644 --- a/libraries/network/build.gradle.kts +++ b/libraries/network/build.gradle.kts @@ -23,7 +23,6 @@ android { buildTypes { release { - isMinifyEnabled = true consumerProguardFiles("consumer-rules.pro") } } diff --git a/libraries/pushproviders/firebase/build.gradle.kts b/libraries/pushproviders/firebase/build.gradle.kts index 28b58b1faa..1446c17c6a 100644 --- a/libraries/pushproviders/firebase/build.gradle.kts +++ b/libraries/pushproviders/firebase/build.gradle.kts @@ -26,7 +26,6 @@ android { buildTypes { getByName("release") { - isMinifyEnabled = true consumerProguardFiles("consumer-proguard-rules.pro") resValue( type = "string", From 20d02785f947d55cc7600c16a98709419c40912b Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 9 Aug 2024 15:04:49 +0100 Subject: [PATCH 088/186] Fix `build_rust_sdk.sh` script to work on linux (#3291) A few linux distributions don't have `gdate`, but I think they should all have `date`. --- tools/sdk/build_rust_sdk.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/sdk/build_rust_sdk.sh b/tools/sdk/build_rust_sdk.sh index 2e4be2e6aa..06662a36e6 100755 --- a/tools/sdk/build_rust_sdk.sh +++ b/tools/sdk/build_rust_sdk.sh @@ -7,7 +7,12 @@ set -e read -p "Do you want to build the Rust SDK from local source (yes/no) default to yes? " buildLocal buildLocal=${buildLocal:-yes} -date=$(gdate +%Y%m%d%H%M%S) +if [[ "$OSTYPE" == "linux-gnu"* ]]; then + date=$(date +%Y%m%d%H%M%S) +else + date=$(gdate +%Y%m%d%H%M%S) +fi + elementPwd=$(pwd) # Ask for the Rust SDK local source path From 92ec946ef04c5b50327e2ce07523c8c1ae37668a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Sun, 11 Aug 2024 09:55:24 +0200 Subject: [PATCH 089/186] Try fixing proguard config for nightly builds --- libraries/pushproviders/firebase/build.gradle.kts | 1 + libraries/pushproviders/firebase/proguard-rules.pro | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 libraries/pushproviders/firebase/proguard-rules.pro diff --git a/libraries/pushproviders/firebase/build.gradle.kts b/libraries/pushproviders/firebase/build.gradle.kts index 1446c17c6a..05dbf2efbb 100644 --- a/libraries/pushproviders/firebase/build.gradle.kts +++ b/libraries/pushproviders/firebase/build.gradle.kts @@ -51,6 +51,7 @@ android { register("nightly") { isMinifyEnabled = true consumerProguardFiles("consumer-proguard-rules.pro") + proguardFiles("proguard-rules.pro") matchingFallbacks += listOf("release") resValue( type = "string", diff --git a/libraries/pushproviders/firebase/proguard-rules.pro b/libraries/pushproviders/firebase/proguard-rules.pro new file mode 100644 index 0000000000..82fb72d95e --- /dev/null +++ b/libraries/pushproviders/firebase/proguard-rules.pro @@ -0,0 +1,5 @@ +# Used for unit tests + +-dontwarn java.lang.invoke.StringConcatFactory + +-keep class io.element.android.libraries.pushproviders.firebase.** { *; } From 43fb47f7afe69ea892ee49b09a0715147a0ec097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Sun, 11 Aug 2024 10:23:22 +0200 Subject: [PATCH 090/186] Add proguard file for firebase for release variant too --- libraries/pushproviders/firebase/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/pushproviders/firebase/build.gradle.kts b/libraries/pushproviders/firebase/build.gradle.kts index 05dbf2efbb..57f3b0b8ae 100644 --- a/libraries/pushproviders/firebase/build.gradle.kts +++ b/libraries/pushproviders/firebase/build.gradle.kts @@ -27,6 +27,7 @@ android { buildTypes { getByName("release") { consumerProguardFiles("consumer-proguard-rules.pro") + proguardFiles("proguard-rules.pro") resValue( type = "string", name = "google_app_id", From f9e3a6752190335bae6935d40b56531d29138bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Sun, 11 Aug 2024 12:32:28 +0200 Subject: [PATCH 091/186] Try removing `isMinified` instead. This should now be controlled at the `app` module level. --- libraries/pushproviders/firebase/build.gradle.kts | 3 --- libraries/pushproviders/firebase/proguard-rules.pro | 5 ----- 2 files changed, 8 deletions(-) delete mode 100644 libraries/pushproviders/firebase/proguard-rules.pro diff --git a/libraries/pushproviders/firebase/build.gradle.kts b/libraries/pushproviders/firebase/build.gradle.kts index 57f3b0b8ae..1e6d88ec53 100644 --- a/libraries/pushproviders/firebase/build.gradle.kts +++ b/libraries/pushproviders/firebase/build.gradle.kts @@ -27,7 +27,6 @@ android { buildTypes { getByName("release") { consumerProguardFiles("consumer-proguard-rules.pro") - proguardFiles("proguard-rules.pro") resValue( type = "string", name = "google_app_id", @@ -50,9 +49,7 @@ android { ) } register("nightly") { - isMinifyEnabled = true consumerProguardFiles("consumer-proguard-rules.pro") - proguardFiles("proguard-rules.pro") matchingFallbacks += listOf("release") resValue( type = "string", diff --git a/libraries/pushproviders/firebase/proguard-rules.pro b/libraries/pushproviders/firebase/proguard-rules.pro deleted file mode 100644 index 82fb72d95e..0000000000 --- a/libraries/pushproviders/firebase/proguard-rules.pro +++ /dev/null @@ -1,5 +0,0 @@ -# Used for unit tests - --dontwarn java.lang.invoke.StringConcatFactory - --keep class io.element.android.libraries.pushproviders.firebase.** { *; } From 8bd48fdc605d8cb7f2c8b2539e20136218413c76 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 12 Aug 2024 07:03:23 +0100 Subject: [PATCH 092/186] Sync Strings (#3297) Co-authored-by: bmarty <3940906+bmarty@users.noreply.github.com> --- .../src/main/res/values-sv/translations.xml | 1 + .../src/main/res/values-sv/translations.xml | 11 + .../src/main/res/values-uk/translations.xml | 11 + .../src/main/res/values-sv/translations.xml | 41 + .../src/main/res/values-uk/translations.xml | 41 + .../main/res/values-pt-rBR/translations.xml | 1 + .../src/main/res/values-sv/translations.xml | 3 + .../src/main/res/values-uk/translations.xml | 4 + .../src/main/res/values-sv/translations.xml | 4 + .../src/main/res/values-uk/translations.xml | 4 + .../src/main/res/values-el/translations.xml | 2 +- .../src/main/res/values-sv/translations.xml | 4 + .../src/main/res/values-uk/translations.xml | 7 + .../src/main/res/values-sv/translations.xml | 4 + .../src/main/res/values-uk/translations.xml | 8 +- .../src/main/res/values-sv/translations.xml | 10 + .../src/main/res/values-uk/translations.xml | 14 +- .../src/main/res/values-be/translations.xml | 2 + .../src/main/res/values-hu/translations.xml | 2 + .../src/main/res/values-sv/translations.xml | 2 + .../src/main/res/values-uk/translations.xml | 3 + .../src/main/res/values-et/translations.xml | 12 +- .../src/main/res/values-hu/translations.xml | 6 + .../src/main/res/values-sv/translations.xml | 6 + .../src/main/res/values-uk/translations.xml | 8 +- .../src/main/res/values-uk/translations.xml | 5 + .../src/main/res/values-sv/translations.xml | 3 + .../src/main/res/values-uk/translations.xml | 26 +- .../impl/src/main/res/values/localazy.xml | 1 + .../src/main/res/values-uk/translations.xml | 11 + .../src/main/res/values-uk/translations.xml | 11 + .../src/main/res/values-uk/translations.xml | 11 + .../src/main/res/values-be/translations.xml | 25 + .../src/main/res/values-et/translations.xml | 12 +- .../src/main/res/values-hu/translations.xml | 20 + .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-ru/translations.xml | 11 + .../src/main/res/values-sk/translations.xml | 11 + .../src/main/res/values-sv/translations.xml | 48 + .../src/main/res/values-uk/translations.xml | 39 + .../src/main/res/values/localazy.xml | 9 + ...typing_MessagesViewWithTyping_Day_0_de.png | 4 +- ...typing_MessagesViewWithTyping_Day_1_de.png | 4 +- ...es.messages.impl_MessagesView_Day_0_de.png | 3 - ...s.messages.impl_MessagesView_Day_10_de.png | 4 +- ...s.messages.impl_MessagesView_Day_11_de.png | 4 +- ...s.messages.impl_MessagesView_Day_12_de.png | 3 - ...es.messages.impl_MessagesView_Day_3_de.png | 4 +- ...es.messages.impl_MessagesView_Day_4_de.png | 4 +- ...es.messages.impl_MessagesView_Day_5_de.png | 3 - ...es.messages.impl_MessagesView_Day_6_de.png | 4 +- ...es.messages.impl_MessagesView_Day_7_de.png | 4 +- ...es.messages.impl_MessagesView_Day_8_de.png | 4 +- ...es.messages.impl_MessagesView_Day_9_de.png | 4 +- screenshots/html/data.js | 1126 +++++++++-------- 55 files changed, 1026 insertions(+), 605 deletions(-) create mode 100644 features/joinroom/impl/src/main/res/values-sv/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-uk/translations.xml create mode 100644 features/roomaliasresolver/impl/src/main/res/values-sv/translations.xml create mode 100644 features/roomaliasresolver/impl/src/main/res/values-uk/translations.xml create mode 100644 libraries/permissions/impl/src/main/res/values-uk/translations.xml create mode 100644 libraries/pushproviders/firebase/src/main/res/values-uk/translations.xml create mode 100644 libraries/pushproviders/unifiedpush/src/main/res/values-uk/translations.xml create mode 100644 libraries/troubleshoot/impl/src/main/res/values-uk/translations.xml delete mode 100644 screenshots/de/features.messages.impl_MessagesView_Day_0_de.png delete mode 100644 screenshots/de/features.messages.impl_MessagesView_Day_12_de.png delete mode 100644 screenshots/de/features.messages.impl_MessagesView_Day_5_de.png diff --git a/features/call/impl/src/main/res/values-sv/translations.xml b/features/call/impl/src/main/res/values-sv/translations.xml index 8b76a70818..b5ee7bc2da 100644 --- a/features/call/impl/src/main/res/values-sv/translations.xml +++ b/features/call/impl/src/main/res/values-sv/translations.xml @@ -3,4 +3,5 @@ "Pågående samtal" "Tryck för att återgå till samtalet" "☎️ Samtal pågår" + "Inkommande Element Call" diff --git a/features/joinroom/impl/src/main/res/values-sv/translations.xml b/features/joinroom/impl/src/main/res/values-sv/translations.xml new file mode 100644 index 0000000000..0181a01381 --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-sv/translations.xml @@ -0,0 +1,11 @@ + + + "Gå med i rummet" + "Knacka för att gå med" + "%1$s stöder inte utrymmen än. Du kan komma åt utrymmen på webben." + "Utrymmen stöds inte ännu" + "Klicka på knappen nedan så kommer en rumsadministratör att meddelas. Du kommer att kunna gå med i konversationen när den har godkänts." + "Du måste vara medlem i det här rummet för att se meddelandehistoriken." + "Vill du gå med i det här rummet?" + "Förhandsgranskning är inte tillgänglig" + diff --git a/features/joinroom/impl/src/main/res/values-uk/translations.xml b/features/joinroom/impl/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..ba19245e40 --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-uk/translations.xml @@ -0,0 +1,11 @@ + + + "Приєднатися до кімнати" + "Постукати, щоб приєднатися" + "%1$s ще не підтримує простори. Ви можете отримати доступ до них в вебверсії." + "Простори поки що не підтримуються" + "Натисніть кнопку нижче, і адміністратор кімнати отримає сповіщення. Ви зможете приєднатися до розмови після схвалення." + "Ви мусите бути учасником цієї кімнати, щоб переглядати історію повідомлень." + "Хочете приєднатися до цієї кімнати?" + "Попередній перегляд недоступний" + diff --git a/features/login/impl/src/main/res/values-sv/translations.xml b/features/login/impl/src/main/res/values-sv/translations.xml index 0362c6c0d0..d50610adcc 100644 --- a/features/login/impl/src/main/res/values-sv/translations.xml +++ b/features/login/impl/src/main/res/values-sv/translations.xml @@ -30,7 +30,48 @@ "Matrix är ett öppet nätverk för säker, decentraliserad kommunikation." "Välkommen tillbaka!" "Logga in på %1$s" + "Upprättar en säker anslutning" + "En säker anslutning kunde inte göras till den nya enheten. Dina befintliga enheter är fortfarande säkra och du behöver inte oroa dig för dem." + "Nu då?" + "Pröva att logga in igen med en QR-kod ifall detta skulle vara ett nätverksproblem" + "Om du stöter på samma problem, prova ett annat wifi-nätverk eller använd din mobildata istället för wifi" + "Om det inte fungerar, logga in manuellt" + "Anslutningen är inte säker" + "Du kommer att bli ombedd att ange de två siffrorna som visas på den här enheten." + "Ange numret nedan på din andra enhet" + "Logga in på din andra enhet och försök sedan igen, eller använd en annan enhet som redan är inloggad." + "Den andra enheten är inte inloggad" + "Inloggningen avbröts på den andra enheten." + "Inloggningsförfrågan avbröts" + "Inloggningen avvisades på den andra enheten." + "Inloggning avvisad" + "Inloggningen har löpt ut. Vänligen försök igen." + "Inloggningen slutfördes inte i tid" + "Din andra enhet stöder inte inloggning i %s med en QR-kod. + +Prova att logga in manuellt eller skanna QR-koden med en annan enhet." + "QR-kod stöds inte" + "Din kontoleverantör stöder inte %1$s." + "%1$s stöds inte" + "Redo att skanna" + "Öppna %1$s på en skrivbordsenhet" + "Klicka på din avatar" + "Välj %1$s" + "”Länka ny enhet”" + "Skanna QR-koden med den här enheten" + "Öppna %1$s på en annan enhet för att få QR-koden" + "Använd QR-koden som visas på den andra enheten." "Försök igen" + "Fel QR-kod" + "Gå till kamerainställningar" + "Du måste ge tillstånd för %1$s att använda enhetens kamera för att kunna fortsätta." + "Tillåt kameraåtkomst för att skanna QR-koden" + "Skanna QR-koden" + "Börja om" + "Ett oväntat fel inträffade. Vänligen försök igen." + "Väntar på din andra enhet" + "Din kontoleverantör kan be om följande kod för att verifiera inloggningen." + "Din verifieringskod" "Byt kontoleverantör" "En privat server för Element-anställda." "Matrix är ett öppet nätverk för säker, decentraliserad kommunikation." diff --git a/features/login/impl/src/main/res/values-uk/translations.xml b/features/login/impl/src/main/res/values-uk/translations.xml index 1e01a8eba0..9cb6eb1f5f 100644 --- a/features/login/impl/src/main/res/values-uk/translations.xml +++ b/features/login/impl/src/main/res/values-uk/translations.xml @@ -30,7 +30,48 @@ "Matrix — це відкрита мережа для безпечної, децентралізованої комунікації." "З поверненням!" "Увійти в %1$s" + "Встановлення безпечного з\'єднання" + "Не вдалося встановити безпечне з\'єднання з новим пристроєм. Ваші існуючі пристрої все ще в безпеці, і вам не потрібно про них турбуватися." + "Що тепер?" + "Спробуйте увійти ще раз за допомогою QR-коду, якщо це була проблема з мережею" + "Якщо ви зіткнулися з тією ж проблемою, спробуйте іншу мережу Wi-Fi або використовуйте мобільний інтернет замість Wi-Fi" + "Якщо це не спрацює, увійдіть вручну" + "З\'єднання не є безпечним" + "Вас попросять ввести дві цифри, показані на цьому пристрої." + "Введіть номер нижче на іншому пристрої" + "Увійдіть на іншому пристрої та спробуйте ще раз або скористайтеся іншим пристроєм, що вже в обліковому записі." + "Інший пристрій не ввійшов" + "Вхід було скасовано на іншому пристрої." + "Запит на вхід скасовано" + "Вхід був відхилений на іншому пристрої." + "Вхід відхилено" + "Термін входу сплив. Будь ласка, спробуйте ще раз." + "Вхід не було завершено вчасно" + "Ваш інший пристрій не підтримує вхід у %s за допомогою QR-коду. + +Спробуйте ввійти вручну або відскануйте QR-код за допомогою іншого пристрою." + "QR-код не підтримується" + "Постачальник вашого облікового запису не підтримує %1$s." + "%1$s не підтримується" + "Готовий до сканування" + "Відкрийте %1$s на комп\'ютері" + "Натисніть на свою аватарку" + "Оберіть %1$s" + "“Підключити новий пристрій”" + "Відскануйте QR-код цим пристроєм" + "Відкрийте %1$s на іншому пристрої, щоб отримати QR-код" + "Використовуйте QR-код, показаний на іншому пристрої." "Спробуйте ще раз" + "Неправильний QR-код" + "Перейти до налаштувань камери" + "Вам потрібно дати дозвіл %1$s на використання камери вашого пристрою, щоб продовжити." + "Надайте доступ до камери, щоб сканувати QR-код" + "Відскануйте QR-код" + "Почати спочатку" + "Сталася несподівана помилка. Будь ласка, спробуйте ще раз." + "Чекаємо на ваш інший пристрій" + "Постачальник облікового запису може попросити вас ввести код нижче для підтвердження входу." + "Ваш код підтвердження" "Змінити провайдера облікового запису" "Приватний сервер для співробітників Element." "Matrix — це відкрита мережа для безпечної, децентралізованої комунікації." diff --git a/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml b/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml index 5fbc14c47a..6255c7c2c9 100644 --- a/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml @@ -43,6 +43,7 @@ Se você continuar, algumas de suas configurações poderão mudar." "Menções" "Me notifique para" "Notifique-me em @room" + "Para receber notificações, altere seu %1$s." "configurações do sistema" "Notificações do sistema desativadas" "Notificações" diff --git a/features/preferences/impl/src/main/res/values-sv/translations.xml b/features/preferences/impl/src/main/res/values-sv/translations.xml index a4ce5bc50c..aa765bc080 100644 --- a/features/preferences/impl/src/main/res/values-sv/translations.xml +++ b/features/preferences/impl/src/main/res/values-sv/translations.xml @@ -1,11 +1,14 @@ + "För att säkerställa att du aldrig missar ett viktigt samtal, ändra dina inställningar för att tillåta helskärmsmeddelanden när telefonen är låst." + "Förbättra din samtalsupplevelse" "Välj hur du vill ta emot aviseringar" "Utvecklarläge" "Aktivera för att ha tillgång till funktionalitet för utvecklare." "Anpassad bas-URL för Element Call" "Ange en anpassad bas-URL för Element Call." "Ogiltig URL, se till att du inkluderar protokollet (http/https) och rätt adress." + "Pushnotisleverantör" "Inaktivera rik-text-redigeraren för att skriva Markdown manuellt." "Läskvitton" "Om det är avstängt kommer dina läskvitton inte att skickas till någon. Du kommer fortfarande att få läskvitton från andra användare." diff --git a/features/preferences/impl/src/main/res/values-uk/translations.xml b/features/preferences/impl/src/main/res/values-uk/translations.xml index 0fdf2a67ad..8905fb3366 100644 --- a/features/preferences/impl/src/main/res/values-uk/translations.xml +++ b/features/preferences/impl/src/main/res/values-uk/translations.xml @@ -1,11 +1,13 @@ + "Щоб ніколи не пропустити важливий дзвінок, змініть налаштування, щоб увімкнути повноекранні сповіщення, коли телефон заблоковано." "Виберіть спосіб отримання сповіщень" "Режим розробника" "Увімкніть доступ до функцій і можливостей для розробників." "Користувацька URL-адреса Element Call" "Встановіть URL-адресу для Element Call." "Неправильна URL-адреса, будь ласка, переконайтеся, що ви вказали протокол (http/https) та правильну адресу." + "Постачальник push-сповіщень" "Вимкніть редактор розширеного тексту, щоб вводити Markdown вручну." "Читати журнали" "Якщо вимкнено, ваші сповіщення про прочитання нікому не надсилатимуться. Ви все одно отримуватимете сповіщення про прочитання від інших користувачів." @@ -50,4 +52,6 @@ "системні налаштування" "Системні сповіщення вимкнені" "Сповіщення" + "Усунення несправностей" + "Усунення неполадок сповіщень" diff --git a/features/roomaliasresolver/impl/src/main/res/values-sv/translations.xml b/features/roomaliasresolver/impl/src/main/res/values-sv/translations.xml new file mode 100644 index 0000000000..8bcfb3f809 --- /dev/null +++ b/features/roomaliasresolver/impl/src/main/res/values-sv/translations.xml @@ -0,0 +1,4 @@ + + + "Misslyckades med att slå upp rumsalias." + diff --git a/features/roomaliasresolver/impl/src/main/res/values-uk/translations.xml b/features/roomaliasresolver/impl/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..0f5d40f6d8 --- /dev/null +++ b/features/roomaliasresolver/impl/src/main/res/values-uk/translations.xml @@ -0,0 +1,4 @@ + + + "Не вдалося розв\'язати псевдонім кімнати." + diff --git a/features/roomdetails/impl/src/main/res/values-el/translations.xml b/features/roomdetails/impl/src/main/res/values-el/translations.xml index 2c1886ce40..57874ff30b 100644 --- a/features/roomdetails/impl/src/main/res/values-el/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-el/translations.xml @@ -63,7 +63,7 @@ "Δεν θα μπορεί να συμμετέχει ξανά σε αυτό το δωμάτιο εάν προσκληθεί." "Θες σίγουρα να αποκλείσεις αυτό το μέλος;" "Δεν υπάρχουν αποκλεισμένοι χρήστες σε αυτό το δωμάτιο." - "Αποκλεισμός του χρήστη %1$s" + "Αποκλεισμός %1$s" "%1$d άτομο" "%1$d άτομα" diff --git a/features/roomdetails/impl/src/main/res/values-sv/translations.xml b/features/roomdetails/impl/src/main/res/values-sv/translations.xml index aec11eed32..eed1cfcbb1 100644 --- a/features/roomdetails/impl/src/main/res/values-sv/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sv/translations.xml @@ -25,6 +25,7 @@ "Degradera dig själv?" "%1$s (Väntar)" "(Väntar)" + "Administratörer har automatiskt moderatorbehörighet" "Redigera moderatorer" "Administratörer" "Moderatorer" @@ -34,6 +35,9 @@ "Lägg till ämne" "Redan medlem" "Redan inbjuden" + "Krypterat" + "Inte krypterat" + "Offentligt rum" "Redigera rummet" "Ett okänt fel uppstod och informationen kunde inte ändras." "Kunde inte uppdatera rummet" diff --git a/features/roomdetails/impl/src/main/res/values-uk/translations.xml b/features/roomdetails/impl/src/main/res/values-uk/translations.xml index b06ad30097..87251699c1 100644 --- a/features/roomdetails/impl/src/main/res/values-uk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-uk/translations.xml @@ -23,6 +23,9 @@ "Понизити" "Ви не зможете скасувати цю зміну, оскільки ви знижуєте себе, якщо ви останній привілейований користувач у кімнаті, відновити привілеї буде неможливо." "Понизити себе?" + "%1$s (Очікується)" + "(Очікується)" + "Адміністратори автоматично мають права модератора" "Керувати модераторами" "Адміністратори" "Модератори" @@ -32,6 +35,9 @@ "Додати тему" "Уже учасник" "Уже запрошені" + "Зашифровано" + "Не зашифровано" + "Публічна кімната" "Редагувати кімнату" "Сталася невідома помилка, й інформацію не вдалося змінити." "Не вдалося оновити кімнату" @@ -50,6 +56,7 @@ "Назва кімнати" "Безпека" "Поділитися кімнатою" + "Інформація про кімнату" "Тема" "Оновлення кімнати…" "Заблокувати" diff --git a/features/roomlist/impl/src/main/res/values-sv/translations.xml b/features/roomlist/impl/src/main/res/values-sv/translations.xml index 69d5dc7cf3..4f7b26bb52 100644 --- a/features/roomlist/impl/src/main/res/values-sv/translations.xml +++ b/features/roomlist/impl/src/main/res/values-sv/translations.xml @@ -2,6 +2,8 @@ "Din chattsäkerhetskopia är för närvarande inte synkroniserad. Du måste ange din återställningsnyckel för att behålla åtkomsten till din chattsäkerhetskopia." "Ange din återställningsnyckel" + "För att säkerställa att du aldrig missar ett viktigt samtal, ändra dina inställningar för att tillåta helskärmsmeddelanden när telefonen är låst." + "Förbättra din samtalsupplevelse" "Är du säker på att du vill tacka nej till inbjudan att gå med%1$s?" "Avböj inbjudan" "Är du säker på att du vill avböja denna privata chatt med %1$s?" @@ -17,6 +19,8 @@ "Du kan lägga till en chatt till dina favoriter i chattinställningarna. För tillfället kan du avmarkera filter för att se dina andra chattar" "Du har inga favoritchattar än" + "Inbjudningar" + "Du har inga väntande inbjudningar." "Låg prioritet" "Du kan avmarkera filter för att se dina andra chattar" "Du har inga chattar för det här valet" diff --git a/features/roomlist/impl/src/main/res/values-uk/translations.xml b/features/roomlist/impl/src/main/res/values-uk/translations.xml index a7f1c26db0..8b33aee7e4 100644 --- a/features/roomlist/impl/src/main/res/values-uk/translations.xml +++ b/features/roomlist/impl/src/main/res/values-uk/translations.xml @@ -2,6 +2,7 @@ "Ваша резервна копія чату наразі не синхронізована. Вам потрібно підтвердити ключ відновлення, щоб зберегти доступ до резервної копії чату." "Підтвердіть ключ відновлення" + "Щоб ніколи не пропустити важливий дзвінок, змініть налаштування, щоб увімкнути повноекранні сповіщення, коли телефон заблоковано." "Ви впевнені, що хочете відхилити запрошення приєднатися до %1$s?" "Відхилити запрошення" "Ви дійсно хочете відмовитися від приватного чату з %1$s?" @@ -17,6 +18,8 @@ "Ви можете додати чат до улюблених у налаштуваннях чату. Наразі ви можете зняти фільтри, щоб побачити інші ваші чати" "Ви ще не маєте улюблених чатів" + "Запрошення" + "У вас немає запрошень, що очікують на розгляд." "Низький пріоритет" "Ви можете зняти фільтри, щоб побачити інші ваші чати" "Ви не маєте чатів для цієї категорії" @@ -28,8 +31,9 @@ "Вітаємо! У вас немає непрочитаних повідомлень!" "Усі чати" - "Позначити як прочитане" - "Позначити як непрочитане" + "Позначити прочитаним" + "Позначити непрочитаним" + "Переглянути всі кімнати" "Схоже, Ви використовуєте новий пристрій. Щоб отримати доступ до зашифрованих повідомлень, підтвердьте особу за допомогою іншого пристрою." "Підтвердьте, що це Ви" diff --git a/features/securebackup/impl/src/main/res/values-sv/translations.xml b/features/securebackup/impl/src/main/res/values-sv/translations.xml index a1b1512031..5216a7ed96 100644 --- a/features/securebackup/impl/src/main/res/values-sv/translations.xml +++ b/features/securebackup/impl/src/main/res/values-sv/translations.xml @@ -9,6 +9,13 @@ "Din chattsäkerhetskopia är för närvarande osynkroniserad." "Ställ in återställning" "Få tillgång till dina krypterade meddelanden om du tappar bort alla dina enheter eller blir utloggad ur %1$s överallt." + "Öppna %1$s på en skrivbordsenhet" + "Logga in på ditt konto igen" + "När du ombeds att verifiera din enhet, välj %1$s" + "”Återställ alla”" + "Följ anvisningarna för att skapa en ny återställningsnyckel" + "Spara din nya återställningsnyckel i en lösenordshanterare eller krypterad anteckning" + "Återställ krypteringen för ditt konto med en annan enhet" "Stäng av" "Du kommer att förlora dina krypterade meddelanden om du loggas ut från alla enheter." "Är du säker på att du vill stänga av säkerhetskopiering?" @@ -21,11 +28,14 @@ "Se till att du kan lagra din återställningsnyckel någonstans säkert" "Återställningsnyckel ändrad" "Byt återställningsnyckel?" + "Skapa ny återställningsnyckel" "Se till att ingen kan se den här skärmen" "Vänligen pröva igen för att bekräfta åtkomsten till din chattsäkerhetskopia." "Felaktig återställningsnyckel" "Om du har en säkerhetsnyckel eller säkerhetsfras så funkar den också." + "Återställningsnyckel eller lösenkod" "Ange …" + "Blivit av med din återställningsnyckel?" "Återställningsnyckel bekräftad" "Ange din återställningsnyckel" "Kopierade återställningsnyckel" diff --git a/features/securebackup/impl/src/main/res/values-uk/translations.xml b/features/securebackup/impl/src/main/res/values-uk/translations.xml index 2a5b029a6b..1d1b9d2526 100644 --- a/features/securebackup/impl/src/main/res/values-uk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-uk/translations.xml @@ -9,6 +9,13 @@ "Ваша резервна копія чату наразі не синхронізована." "Налаштувати відновлення" "Отримайте доступ до своїх зашифрованих повідомлень, якщо ви втратите всі свої пристрої або вийшли з %1$s системи." + "Відкрийте %1$s на комп\'ютері" + "Увійдіть до вашого облікового запису знову" + "Коли вас попросять підтвердити пристрій, виберіть %1$s" + "“Скинути все”" + "Дотримуйтесь інструкцій, щоб створити новий ключ відновлення" + "Збережіть новий ключ відновлення у менеджері паролів або зашифрованій нотатці" + "Скинути шифрування облікового запису за допомогою іншого пристрою" "Вимкнути" "Ви втратите зашифровані повідомлення, якщо вийдете з усіх пристроїв." "Ви впевнені, що хочете вимкнути резервне копіювання?" @@ -21,11 +28,14 @@ "Переконайтеся, що ви можете зберігати ключ відновлення в безпечному місці" "Ключ відновлення змінено" "Змінити ключ відновлення?" - "Введіть ключ відновлення, щоб підтвердити доступ до резервної копії чату." + "Створити новий ключ відновлення" + "Впевніться, що ніхто не дивиться!" "Будь ласка, спробуйте ще раз, щоб підтвердити доступ до резервної копії чату." "Неправильний ключ відновлення" - "Введіть код із 48 символів." + "Якщо у вас є ключ безпеки або фраза безпеки, це теж спрацює." + "Ключ відновлення або код допуску" "Ввести…" + "Загубили ключ відновлення?" "Ключ відновлення підтверджено" "Підтвердіть ключ відновлення" "Скопійовано ключ відновлення" diff --git a/features/verifysession/impl/src/main/res/values-be/translations.xml b/features/verifysession/impl/src/main/res/values-be/translations.xml index 5399805c90..cdb8cedfe0 100644 --- a/features/verifysession/impl/src/main/res/values-be/translations.xml +++ b/features/verifysession/impl/src/main/res/values-be/translations.xml @@ -1,9 +1,11 @@ + "Не можаце пацвердзіць?" "Стварыць новы ключ аднаўлення" "Пацвердзіце гэтую прыладу, каб наладзіць бяспечны абмен паведамленнямі." "Пацвердзіце, што гэта вы" "Выкарыстоўвайце іншую прыладу" + "Выкарыстоўваць ключ аднаўлення" "Цяпер вы можаце бяспечна чытаць і адпраўляць паведамленні, і ўсе, з кім вы маеце зносіны ў чаце, таксама могуць давяраць гэтай прыладзе." "Прылада праверана" "Выкарыстоўвайце іншую прыладу" diff --git a/features/verifysession/impl/src/main/res/values-hu/translations.xml b/features/verifysession/impl/src/main/res/values-hu/translations.xml index 34656caeae..3de5d84c48 100644 --- a/features/verifysession/impl/src/main/res/values-hu/translations.xml +++ b/features/verifysession/impl/src/main/res/values-hu/translations.xml @@ -1,9 +1,11 @@ + "Nem tudja megerősíteni?" "Új helyreállítási kulcs létrehozása" "A biztonságos üzenetkezelés beállításához ellenőrizze ezt az eszközt." "Erősítse meg, hogy Ön az" "Másik eszköz használata" + "Helyreállítási kulcs használata" "Mostantól biztonságosan olvashat vagy küldhet üzeneteket, és bármelyik csevegőpartnere megbízhat ebben az eszközben." "Eszköz ellenőrizve" "Másik eszköz használata" diff --git a/features/verifysession/impl/src/main/res/values-sv/translations.xml b/features/verifysession/impl/src/main/res/values-sv/translations.xml index c65d66d0a4..524bc02b1e 100644 --- a/features/verifysession/impl/src/main/res/values-sv/translations.xml +++ b/features/verifysession/impl/src/main/res/values-sv/translations.xml @@ -1,9 +1,11 @@ + "Kan du inte bekräfta?" "Skapa en ny återställningsnyckel" "Verifiera den här enheten för att konfigurera säkra meddelanden." "Bekräfta att det är du" "Använd en annan enhet" + "Använd återställningsnyckel" "Nu kan du läsa eller skicka meddelanden säkert, och alla du chattar med kan också lita på den här enheten." "Enhet verifierad" "Använd en annan enhet" diff --git a/features/verifysession/impl/src/main/res/values-uk/translations.xml b/features/verifysession/impl/src/main/res/values-uk/translations.xml index 9be10a2bb0..b76304f537 100644 --- a/features/verifysession/impl/src/main/res/values-uk/translations.xml +++ b/features/verifysession/impl/src/main/res/values-uk/translations.xml @@ -1,9 +1,12 @@ + "Не можете підтвердити?" + "Створити новий ключ відновлення" "Перевірте цей пристрій, щоб налаштувати безпечний обмін повідомленнями." "Підтвердіть, що це ви" "Тепер ви можете безпечно читати або надсилати повідомлення, і кожен, з ким ви спілкуєтесь, також може довіряти цьому пристрою." "Пристрій перевірено" + "Чекає на інше пристрій…" "Щось не так. Або час очікування запиту минув, або в запиті було відмовлено." "Переконайтеся, що емодзі нижче збігаються з тими, що відображаються під час іншого сеансу." "Порівняти емодзі" diff --git a/libraries/eventformatter/impl/src/main/res/values-et/translations.xml b/libraries/eventformatter/impl/src/main/res/values-et/translations.xml index 1d265d4004..506f22db55 100644 --- a/libraries/eventformatter/impl/src/main/res/values-et/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-et/translations.xml @@ -45,12 +45,12 @@ "Sina eemaldasid jututoa nime" "%1$s ei teinud ühtegi muudatust" "Sina ei teinud ühtegi muudatust" - "%1$s muutis klammerdatud sõnumeid" - "Sina muutsid klammerdatud sõnumeid" - "%1$s klammerdas sõnumi" - "Sina klammerdasid sõnumi" - "%1$s eemaldas klammerdatud sõnumi" - "Sina eemaldasid klammerdatud sõnumi" + "%1$s muutis esiletõstetud sõnumeid" + "Sina muutsid esiletõstetud sõnumeid" + "%1$s tõstis sõnumi esile" + "Sina tõstsid sõnumi esile" + "%1$s eemaldas esiletõstetud sõnumi" + "Sina eemaldasid esiletõstetud sõnumi" "%1$s lükkas kutse tagasi" "Sina lükkasid kutse tagasi" "%1$s eemaldas jututoast kasutaja %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-hu/translations.xml b/libraries/eventformatter/impl/src/main/res/values-hu/translations.xml index c23e973217..879e21c466 100644 --- a/libraries/eventformatter/impl/src/main/res/values-hu/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-hu/translations.xml @@ -45,6 +45,12 @@ "Eltávolította a szoba nevét" "%1$s nem változtatott semmin" "Nem változtatott semmin" + "%1$s megváltoztatta a kitűzött üzeneteket" + "Megváltoztatta a kitűzött üzeneteket" + "%1$s kitűzött egy üzenetet" + "Kitűzött egy üzenetet" + "%1$s feloldotta egy üzenet kitűzését" + "Feloldotta egy üzenet kitűzését" "%1$s elutasította a meghívást" "Elutasította a meghívást" "%1$s eltávolította: %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-sv/translations.xml b/libraries/eventformatter/impl/src/main/res/values-sv/translations.xml index 014f21ee4a..d96f722111 100644 --- a/libraries/eventformatter/impl/src/main/res/values-sv/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-sv/translations.xml @@ -45,6 +45,12 @@ "Du tog bort rummets namn" "%1$s gjorde inga ändringar" "Du gjorde inga ändringar" + "%1$s ändrade de fästa meddelandena" + "Du ändrade de fästa meddelandena" + "%1$s fäste ett meddelande" + "Du har fäste ett meddelande" + "%1$s lossade ett meddelande" + "Du har lossade ett meddelande" "%1$s avvisade inbjudan" "Du avvisade inbjudan" "%1$s tog bort %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-uk/translations.xml b/libraries/eventformatter/impl/src/main/res/values-uk/translations.xml index eccaa950eb..065f08cad4 100644 --- a/libraries/eventformatter/impl/src/main/res/values-uk/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-uk/translations.xml @@ -30,7 +30,7 @@ "Ви приєдналися до кімнати" "%1$s подав (-ла) запит на приєднання" "%1$s дозволив (-ла) %2$s приєднатися" - "%1$s дозволив (-ла) Вам приєднатися" + "Ви дозволили %1$s приєднатися" "Ви подали запит на приєднання" "%1$s відхилив (-ла) запит %2$s на приєднання" "Ви відхилили запит %1$s на приєднання" @@ -45,6 +45,12 @@ "Ви видалили назву кімнати" "%1$s не внесено жодних змін" "Ви не внесли жодних змін" + "%1$s змінив(-ла) закріплені повідомлення" + "Ви змінили закріплені повідомлення" + "%1$s закріпив(-ла) повідомлення" + "Ви закріпили повідомлення" + "%1$s відкріпив(-ла) повідомлення" + "Ви відкріпили повідомлення" "%1$s відхилив (-ла) запрошення" "Ви відхилили запрошення" "%1$s вилучив (-ла) %2$s" diff --git a/libraries/permissions/impl/src/main/res/values-uk/translations.xml b/libraries/permissions/impl/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..09f8671a97 --- /dev/null +++ b/libraries/permissions/impl/src/main/res/values-uk/translations.xml @@ -0,0 +1,5 @@ + + + "Перевірте, чи програма може показувати сповіщення." + "Перевірте дозволи" + diff --git a/libraries/push/impl/src/main/res/values-sv/translations.xml b/libraries/push/impl/src/main/res/values-sv/translations.xml index bf4c19111a..92036e09c2 100644 --- a/libraries/push/impl/src/main/res/values-sv/translations.xml +++ b/libraries/push/impl/src/main/res/values-sv/translations.xml @@ -3,6 +3,7 @@ "Samtal" "Lyssnar efter händelser" "Högljudda aviseringar" + "Ringande samtal" "Tysta aviseringar" "%1$s: %2$d meddelande" @@ -12,6 +13,8 @@ "%d avisering" "%d aviseringar" + "notis" + "Inkommande samtal" "** Misslyckades att skicka - vänligen öppna rummet" "Gå med" "Avvisa" diff --git a/libraries/push/impl/src/main/res/values-uk/translations.xml b/libraries/push/impl/src/main/res/values-uk/translations.xml index e1a3f8bf47..b7e3df3348 100644 --- a/libraries/push/impl/src/main/res/values-uk/translations.xml +++ b/libraries/push/impl/src/main/res/values-uk/translations.xml @@ -3,6 +3,7 @@ "Виклик" "Прослуховування подій" "Гучні сповіщення" + "Дзвінки" "Тихі сповіщення" "%1$s: %2$d повідомлення" @@ -15,6 +16,7 @@ "%d сповіщень" "Сповіщення" + "Вхідний дзвінок" "** Не вдалося надіслати - будь ласка, відкрийте кімнату" "Доєднатися" "Відхилити" @@ -32,7 +34,7 @@ "%d нових повідомлень" "Відреагував (-ла) з %1$s" - "Позначити як прочитане" + "Позначити прочитаним" "Швидка відповідь" "Запросив (-ла) Вас приєднатися до кімнати" "Я" @@ -55,5 +57,27 @@ "Фонова синхронізація" "Сервіси Google" "Не знайдено дійсних сервісів Google Play. Сповіщення можуть не працювати належним чином." + "Отримує назву поточного постачальника." + "Постачальників push-сповіщень не обрано." + "Поточний постачальник: %1$s." + "Поточний провайдер push" + "Переконайтеся, що програма має принаймні один push провайдер." + "Не знайдено постачальників push-повідомлень." + + "Виявлено %1$d постачальника: %2$s" + "Виявлено %1$d постачальників: %2$s" + "Виявлено %1$d постачальників: %2$s" + + "Виявлення push-провайдерів" + "Перевірте, чи може програма відображати сповіщення." + "Ви не натиснули на сповіщення." "Не вдається відобразити сповіщення." + "Ви натиснули на сповіщення!" + "Відображення сповіщення" + "Будь ласка, натисніть на сповіщення, щоб продовжити тест." + "Переконується, що застосунок отримує push-сповіщення." + "Помилка: постачальник push-сповіщень відхилив запит." + "Помилка: %1$s." + "Помилка, неможливо перевірити push." + "Перевірка зворотного надсилання" diff --git a/libraries/push/impl/src/main/res/values/localazy.xml b/libraries/push/impl/src/main/res/values/localazy.xml index e1bfa07d29..5fed2718a1 100644 --- a/libraries/push/impl/src/main/res/values/localazy.xml +++ b/libraries/push/impl/src/main/res/values/localazy.xml @@ -34,6 +34,7 @@ "Quick reply" "Invited you to join the room" "Me" + "%1$s mentioned or replied" "You are viewing the notification! Click me!" "%1$s: %2$s" "%1$s: %2$s %3$s" diff --git a/libraries/pushproviders/firebase/src/main/res/values-uk/translations.xml b/libraries/pushproviders/firebase/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..8024070d70 --- /dev/null +++ b/libraries/pushproviders/firebase/src/main/res/values-uk/translations.xml @@ -0,0 +1,11 @@ + + + "Переконується, що Firebase доступний." + "Firebase недоступний." + "Firebase доступний." + "Перевірка Firebase" + "Переконується, що токен Firebase доступний." + "Токен Firebase невідомий." + "Токен Firebase: %1$s." + "Перевірка токена Firebase" + diff --git a/libraries/pushproviders/unifiedpush/src/main/res/values-uk/translations.xml b/libraries/pushproviders/unifiedpush/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..cad17a7b69 --- /dev/null +++ b/libraries/pushproviders/unifiedpush/src/main/res/values-uk/translations.xml @@ -0,0 +1,11 @@ + + + "Переконується, що дистриб\'ютори UnifiedPush доступні." + "Дистриб\'юторів не знайдено." + + "%1$d дистриб\'ютора знайдено: %2$s." + "%1$d дистриб\'юторів знайдено: %2$s." + "%1$d дистриб\'юторів знайдено: %2$s." + + "Перевірка UnifiedPush" + diff --git a/libraries/troubleshoot/impl/src/main/res/values-uk/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..935c6b517d --- /dev/null +++ b/libraries/troubleshoot/impl/src/main/res/values-uk/translations.xml @@ -0,0 +1,11 @@ + + + "Запустити тести" + "Запустити тести знову" + "Деякі тести не пройшли. Будь ласка, перегляньте деталі." + "Запустіть тести, щоб виявити будь-яку проблему у вашій конфігурації, через яку сповіщення можуть не працювати належним чином." + "Спробувати виправити" + "Всі тести пройшли успішно." + "Усунення неполадок сповіщень" + "Деякі тести вимагають вашої уваги. Будь ласка, перегляньте деталі." + 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 2227fce81f..955c4eab3d 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -93,6 +93,7 @@ "Паведаміць пра памылку" "Паскардзіцца на змест" "Скінуць" + "Скінуць ідэнтыфікацыйныя дадзеныя" "Паўтарыць" "Паўтарыць расшыфроўку" "Захаваць" @@ -112,6 +113,7 @@ "Зрабіць фота" "Дакраніцеся, каб убачыць параметры" "Паўтарыць спробу" + "Адмацаваць" "Прагляд зыходнага кода" "Так" "Аб праграме" @@ -262,6 +264,7 @@ "Некаторыя паведамленні не былі адпраўлены" "Выбачце, адбылася памылка" "Сапраўднасць гэтага зашыфраванага паведамлення не можа быць гарантаваная на гэтай прыладзе." + "Не зашыфраваны." "Зашыфравана невядомай ці выдаленай прыладай." "Зашыфравана прыладай, не пацверджанай яе ўладальнікам." "Зашыфравана неправераным карыстальнікам." @@ -269,9 +272,30 @@ "Гэй, пагавары са мной у %1$s: %2$s" "%1$s Android" "Паведаміць аб памылцы з дапамогай Rageshake" + "Дадзеныя вашага ўліковага запісу, кантакты, налады і спіс чатаў будуць захаваны" + "Вы страціце існуючую гісторыю паведамленняў" + "Вам трэба будзе зноў запэўніць ўсе вашы існуючыя прылады і кантакты" + "Працягвайце, толькі калі вы ўпэўненыя, што страцілі ўсе астатнія прылады і ключ аднаўлення." + "Калі вы не ўвайшлі ў сістэму на іншых прыладах і страцілі ключ аднаўлення, вам неабходна скінуць ключы пацверджання, каб працягнуць выкарыстанне прыкладання." + "Скіньце ключы пацверджання, калі вы не можаце пацвердзіць яго іншым спосабам" "Не ўдалося выбраць носьбіт, паўтарыце спробу." "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз." "Не атрымалася загрузіць медыяфайлы, паспрабуйце яшчэ раз." + "Націсніце на паведамленне і абярыце «%1$s », каб уключыць сюды." + "Замацуеце важныя паведамленні, каб іх можна было лёгка знайсці" + + "%1$d Замацаванае паведамленне" + "%1$d Замацаваныя паведамленні" + "%1$d Замацаваных паведамленняў" + + "Замацаваныя паведамленні" + "Так, скінуць зараз" + "Гэты працэс незваротны." + "Вы ўпэўнены, што хочаце скінуць шыфраванне?" + "Увод…" + "Пацвердзіце, што вы хочаце скінуць шыфраванне" + "Каб працягнуць, увядзіце пароль уліковага запісу" + "Замацаваныя паведамленні" "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз." "Не ўдалося атрымаць інфармацыю пра карыстальніка" "Заблакіраваць" @@ -283,6 +307,7 @@ "Разблакіраваць карыстальніка" "%1$s з %2$s" "%1$s Замацаваныя паведамленні" + "Загрузка паведамлення…" "Паглядзець усе" "Чат" "Падзяліцца месцазнаходжаннем" diff --git a/libraries/ui-strings/src/main/res/values-et/translations.xml b/libraries/ui-strings/src/main/res/values-et/translations.xml index c205c6910f..31e32b2a27 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -260,6 +260,7 @@ Põhjus: %1$s." "Mõned sõnumid on saatmata" "Vabandust, ilmnes viga" "Selle krüptitud sõnumi tõepärasus pole selles seadmes tagatud." + "Pole krüptitud." "Krüptitud tundmatu või kustutatud seadme poolt." "Krüptitud seadme poolt, mida tema omanik pole verifitseerinud." "Krüptitud verifitseerimata kasutaja poolt." @@ -276,12 +277,20 @@ Põhjus: %1$s." "Meediafaili valimine ei õnnestunud. Palun proovi uuesti." "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Meediafaili üleslaadimine ei õnnestunud. Palun proovi uuesti." + "Siia lisamiseks vajuta sõnumil ja vali „%1$s“." + "Et olulisi sõnumeid oleks lihtsam leida, tõsta nad esile" + + "%1$d esiletõstetud sõnum" + "%1$d esiletõstetud sõnumit" + + "Esiletõstetud sõnumid" "Jah, lähtesta nüüd" "See tegevus on tagasipöördumatu." "Kas sa oled kindel, et soovid oma andmete krüptimist lähtestada?" "Sisesta…" "Palun kinnita, et soovid oma andmete krüptimist lähtestada." "Jätkamaks sisesta oma kasutajakonto salasõna" + "Esiletõstetud sõnumid" "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Kasutaja andmete laadimine ei õnnestunud" "Blokeeri" @@ -292,7 +301,8 @@ Põhjus: %1$s." "Nüüd näed sa jälle kõiki tema sõnumeid" "Eemalda kasutajalt blokeering" "%1$s / %2$s" - "%1$s kinnitatud sõnumit" + "%1$s esiletõstetud sõnumit" + "Laadime sõnumit…" "Näita kõiki" "Vestlus" "Jaga asukohta" 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 7692711037..84e16ed265 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -91,6 +91,7 @@ "Hiba jelentése" "Tartalom jelentése" "Visszaállítás" + "Személyazonosság visszaállítása" "Újra" "Visszafejtés újbóli megpróbálása" "Mentés" @@ -110,6 +111,7 @@ "Fénykép készítése" "Koppintson a beállításokért" "Próbálja újra" + "Kitűzés feloldása" "Forrás megtekintése" "Igen" "Névjegy" @@ -258,6 +260,7 @@ Ok: %1$s." "Néhány üzenet nem került elküldésre" "Elnézést, hiba történt" "A titkosított üzenetek valódiságát ezen az eszközön nem lehet garantálni." + "Nincs titkosítva." "Ismeretlen vagy törölt eszköz által titkosítva." "A tulajdonos által nem ellenőrzött eszköz által titkosítva." "Nem ellenőrzött felhasználó által titkosítva." @@ -265,9 +268,22 @@ Ok: %1$s." "Beszélgessünk itt: %1$s, %2$s" "%1$s Android" "Az eszköz rázása a hibajelentéshez" + "A fiókadatok, a kapcsolatok, a beállítások és a csevegéslista megmarad" + "Elveszíti meglévő üzenetelőzményeit" + "Újból ellenőriznie kell az összes meglévő eszközét és csevegőpartnerét" + "Csak akkor állítsa vissza a személyazonosságát, ha nem fér hozzá másik bejelentkezett eszközhöz, és elvesztette a helyreállítási kulcsot." + "Ha nincs bejelentkezve más eszközre, és elvesztette a helyreállítási kulcsot, akkor az alkalmazás használatának folytatásához vissza kell állítania személyazonosságát. " + "Állítsa vissza a személyazonosságát, ha más módon nem tudja megerősíteni" "Nem sikerült kiválasztani a médiát, próbálja újra." "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra." "Nem sikerült a média feltöltése, próbálja újra." + "Igen, visszaállítás most" + "Ez a folyamat visszafordíthatatlan." + "Biztos, hogy visszaállítja a titkosítást?" + "Adja meg…" + "Erősítse meg, hogy vissza szeretné állítani a titkosítást." + "A folytatáshoz adja meg fiókja jelszavát" + "Kitűzött üzenetek" "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra." "Nem sikerült letölteni a felhasználói adatokat" "Letiltás" @@ -277,6 +293,10 @@ Ok: %1$s." "Letiltás feloldása" "Újra láthatja az összes üzenetét." "Felhasználó kitiltásának feloldása" + "%1$s / %2$s" + "%1$s kitűzött üzenet" + "Üzenet betöltése…" + "Összes megtekintése" "Csevegés" "Hely megosztása" "Saját hely megosztása" 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 f389f21fa6..17df3fe3d7 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -124,7 +124,7 @@ "Rozmowa w trakcie (niewspierane)" "Rozpoczęto rozmowę" "Backup czatu" - "Copyright" + "Prawa autorskie" "Tworzenie pokoju…" "Opuścił pokój" "Ciemny" 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 5f4815cc93..d087e9c8d3 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -266,6 +266,7 @@ "Некоторые сообщения не были отправлены" "Извините, произошла ошибка" "Подлинность этого зашифрованного сообщения не может быть гарантирована на этом устройстве." + "Не зашифровано." "Зашифровано неизвестным или удаленным устройством." "Зашифровано устройством, не проверенным его владельцем." "Зашифровано непроверенным пользователем." @@ -282,12 +283,21 @@ "Не удалось выбрать носитель, попробуйте еще раз." "Не удалось обработать медиафайл для загрузки, попробуйте еще раз." "Не удалось загрузить медиафайлы, попробуйте еще раз." + "Нажмите на сообщение и выберите “%1$s”, чтобы добавить его сюда." + "Закрепите важные сообщения, чтобы их можно было легко найти" + + "%1$d Закрепленное сообщение" + "%1$d Закрепленных сообщений" + "%1$d Закрепленных сообщений" + + "Закрепленные сообщения" "Да, сбросить сейчас" "Этот процесс необратим." "Вы действительно хотите сбросить шифрование?" "Ввод…" "Подтвердите, что вы хотите сбросить шифрование." "Введите пароль своей учетной записи, чтобы продолжить" + "Закрепленные сообщения" "Не удалось обработать медиафайл для загрузки, попробуйте еще раз." "Не удалось получить данные о пользователе" "Заблокировать" @@ -299,6 +309,7 @@ "Разблокировать пользователя" "%1$s из %2$s" "%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 4de47203d2..497f2af1fb 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -264,6 +264,7 @@ Dôvod: %1$s." "Niektoré správy neboli odoslané" "Prepáčte, vyskytla sa chyba" "Pravosť tejto šifrovanej správy nie je možné zaručiť na tomto zariadení." + "Nie je šifrované." "Zašifrované neznámym alebo odstráneným zariadením." "Šifrované zariadením, ktoré nie je overené jeho majiteľom." "Šifrované neovereným používateľom." @@ -280,12 +281,21 @@ Dôvod: %1$s." "Nepodarilo sa vybrať médium, skúste to prosím znova." "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa nahrať médiá, 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ť" + + "%1$d pripnutá správa" + "%1$d pripnuté správy" + "%1$d pripnutých správ" + + "Pripnuté správy" "Áno, znovu nastaviť teraz" "Tento proces je nezvratný." "Naozaj chcete obnoviť svoje šifrovanie?" "Zadajte…" "Potvrďte, že chcete obnoviť svoje šifrovanie." "Ak chcete pokračovať, zadajte heslo účtu" + "Pripnuté správy" "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa získať údaje o používateľovi" "Zablokovať" @@ -297,6 +307,7 @@ Dôvod: %1$s." "Odblokovať používateľa" "%1$s z %2$s" "%1$s Pripnutých správ" + "Načítava sa správa…" "Zobraziť všetko" "Konverzácia" "Zdieľať polohu" 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 144e6bda05..cca5e5b12a 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -34,6 +34,7 @@ "Godkänn" "Lägg till i tidslinjen" "Tillbaka" + "Ring" "Avbryt" "Välj bild" "Rensa" @@ -72,21 +73,25 @@ "Ladda mer" "Hantera konto" "Hantera enheter" + "Meddela" "Nästa" "Nej" "Inte nu" "OK" "Inställningar" "Öppna med" + "Fäst" "Snabbsvar" "Citera" "Reagera" + "Avvisa" "Ta bort" "Svara" "Svara i tråd" "Rapportera bugg" "Rapportera innehåll" "Återställ" + "Återställ identitet" "Försök igen" "Försök att avkryptera igen" "Spara" @@ -106,6 +111,7 @@ "Ta ett foto" "Tryck för alternativ" "Försök igen" + "Frigör" "Visa källkod" "Ja" "Om" @@ -117,6 +123,7 @@ "Blockerade användare" "Bubblor" "Samtal pågår (stöds inte)" + "Samtal startat" "Chattsäkerhetskopia" "Upphovsrätt" "Skapar rum …" @@ -125,12 +132,16 @@ "Avkrypteringsfel" "Utvecklaralternativ" "Direktchatt" + "Visa inte detta igen" "(redigerad)" "Redigerar" "* %1$s %2$s" "Kryptering aktiverad" "Ange din PIN-kod" "Fel" + "Ett fel inträffade, du kanske inte får aviseringar för nya meddelanden. Felsök aviseringar från inställningarna. + +Anledning:%1$s." "Alla" "Misslyckades" "Favorit" @@ -158,12 +169,15 @@ "Modernt" "Tysta" "Inga resultat" + "Inget rumsnamn" "Frånkopplad" + "Licenser för öppen källkod" "eller" "Lösenord" "Personer" "Permalänk" "Behörighet" + "Vänligen vänta …" "Är du säker på att du vill avsluta den här omröstningen?" "Omröstning: %1$s" "Totalt antal röster: %1$s" @@ -192,6 +206,7 @@ "Sökresultat" "Säkerhet" "Sett av" + "Skicka till" "Skickar …" "Misslyckades att skicka" "Skickat" @@ -200,6 +215,7 @@ "Inställningar" "Delade plats" "Loggar ut" + "Något gick fel" "Startar chatt …" "Dekal" "Lyckades" @@ -212,6 +228,7 @@ "Ämne" "Vad handlar det här rummet om?" "Kan inte avkryptera" + "Du har inte tillgång till det här meddelandet" "Inbjudan kunde inte skickas till en eller flera användare." "Kunde inte skicka inbjudningar" "Lås upp" @@ -236,18 +253,44 @@ "Misslyckades att ladda meddelanden" "%1$s kunde inte komma åt din plats. Vänligen försök igen senare." "Misslyckades med att ladda upp ditt röstmeddelande." + "Meddelandet hittades inte" "%1$s är inte behörig att komma åt din plats. Du kan aktivera åtkomst i Inställningar." "%1$s är inte behörig att komma åt din plats. Aktivera åtkomst nedan." "%1$s är inte behörig att komma åt din mikrofon. Aktivera åtkomst för att spela in ett röstmeddelande." "Vissa meddelanden har inte skickats" "Tyvärr, ett fel uppstod" + "Detta krypterade meddelandes äkthet kan inte garanteras på den här enheten." + "Inte krypterad." + "Krypterad av en okänd eller raderad enhet." + "Krypterad av en enhet som inte verifierats av ägaren." + "Krypterad av en overifierad användare." "🔐️ Häng med mig på %1$s" "Hallå, prata med mig på %1$s: %2$s" "%1$s Android" "Raseriskaka för att rapportera bugg" + "Dina kontouppgifter, kontakter, inställningar och chattlistor kommer bevaras" + "Du kommer att förlora din befintliga meddelandehistorik" + "Du måste verifiera alla dina befintliga enheter och kontakter igen" + "Återställ bara din identitet om du inte har tillgång till en annan inloggad enhet och du har tappat bort din återställningsnyckel." + "Om du inte är inloggad på någon annan enhet och du har tappat bort din återställningsnyckel måste du återställa din identitet för att fortsätta använda appen. " + "Återställ din identitet ifall du inte kan bekräfta på annat sätt" "Misslyckades att välja media, vänligen pröva igen." "Misslyckades att bearbeta media för uppladdning, vänligen pröva igen." "Misslyckades att ladda upp media, vänligen pröva igen." + "Tryck på ett meddelande och välj ”%1$s” för att inkludera det här." + "Fäst viktiga meddelanden så att de lätt kan upptäckas" + + "%1$d Fäst meddelande" + "%1$d Fästa meddelanden" + + "Fästa meddelanden" + "Ja, återställ nu" + "Denna process är irreversibel." + "Är du säker på att du vill återställa din kryptering?" + "Ange …" + "Bekräfta att du vill återställa din kryptering." + "Ange ditt kontolösenord för att fortsätta" + "Fästa meddelanden" "Misslyckades att bearbeta media för uppladdning, vänligen pröva igen." "Kunde inte hämta användarinformation" "Blockera" @@ -257,6 +300,11 @@ "Avblockera" "Du kommer att kunna se alla meddelanden från dem igen." "Avblockera användare" + "%1$s av %2$s" + "%1$s Fästa meddelanden" + "Laddar meddelande …" + "Visa alla" + "Chatt" "Dela plats" "Dela min plats" "Öppna i Apple Maps" 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 4082bfb6b0..5a8ede8b04 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -36,6 +36,7 @@ "Прийняти" "Додати до стрічки" "Назад" + "Зателефонувати" "Скасувати" "Вибрати фото" "Очистити" @@ -74,21 +75,25 @@ "Завантажити ще" "Керування обліковим записом" "Керування пристроями" + "Написати" "Далі" "Ні" "Не зараз" "Гаразд" "Налаштування" "Відкрити за допомогою" + "Закріпити" "Швидка відповідь" "Цитувати" "Реакція" + "Відхилити" "Вилучити" "Відповісти" "Відповісти в гілці" "Повідомити про помилку" "Повідомити про вміст" "Скинути" + "Скинути ідентичність" "Спробувати ще раз" "Повторити спробу розшифрування" "Зберегти" @@ -108,6 +113,7 @@ "Зробити фото" "Натисніть, щоб переглянути параметри" "Спробуйте ще раз" + "Відкріпити" "Переглянути джерело" "Так" "Відомості" @@ -119,6 +125,7 @@ "Заблоковані користувачі" "Бульбашки" "Триває виклик (не підтримується)" + "Дзвінок розпочато" "Резервне копіювання чату" "Авторське право" "Створення кімнати…" @@ -127,12 +134,16 @@ "Помилка розшифровки" "Налаштування розробника" "Особистий чат" + "Не показувати це знову" "(відредаговано)" "Редагування" "* %1$s %2$s" "Шифрування ввімкнено" "Введіть свій PIN-код" "Помилка" + "Сталася помилка, ви можете не отримувати сповіщення про нові повідомлення. Усуньте неполадки зі сповіщеннями в налаштуваннях. + +Причина: %1$s." "Усі" "Невдало" "Улюблений" @@ -161,12 +172,15 @@ "Модерн" "Вимкнути звук" "Немає результатів" + "Немає назви кімнати" "Не в мережі" + "Ліцензії відкритого коду" "або" "Пароль" "Люди" "Постійне посилання" "Дозвіл" + "Будь ласка, зачекайте…" "Ви впевнені, що хочете закінчити це опитування?" "Опитування: %1$s" "Всього голосів: %1$s" @@ -196,6 +210,7 @@ "Результати пошуку" "Безпека" "Побачили" + "Надіслати до" "Надсилання…" "Не вдалося відправити" "Надіслано" @@ -204,6 +219,7 @@ "Налаштування" "Поширене розташування" "Вихід" + "Щось пішло не так" "Початок чату…" "Наліпка" "Успіх" @@ -216,6 +232,7 @@ "Тема" "Про що ця кімната?" "Неможливо розшифрувати" + "Ви не маєте доступу до цього повідомлення" "Не вдалося надіслати запрошення одному чи кільком користувачам." "Не вдалося надіслати запрошення" "Розблокувати" @@ -240,26 +257,48 @@ "Не вдалося завантажити повідомлення" "%1$s не вдалося отримати доступ до вашого місцезнаходження. Будь ласка, спробуйте ще раз пізніше." "Не вдалося завантажити голосове повідомлення." + "Повідомлення не знайдено" "%1$s не має дозволу на доступ до вашого місцезнаходження. Увімкнути доступ можна в Налаштуваннях." "%1$s не має дозволу на доступ до вашого місцезнаходження. Увімкніть доступ нижче." "%1$s не має доступу до вашого мікрофона. Надайте доступ, щоб записати голосове повідомлення." "Деякі повідомлення не були надіслані" "Вибачте, сталася помилка" + "Автентичність цього зашифрованого повідомлення не може бути гарантована на цьому пристрої." + "Зашифрований невідомим або видаленим пристроєм." + "Зашифровано пристроєм, який не підтверджено його власником." + "Зашифровано неперевіреним користувачем." "🔐️ Приєднуйтеся до мене в %1$s" "Привіт, пишіть мені за адресою %1$s: %2$s" "%1$s Android" "Повідомити про ваду за допомогою Rageshake" + "Дані вашого облікового запису, контакти, налаштування й чати будуть збережені" + "Ви втратите свою наявну історію повідомлень" + "Вам доведеться підтвердити всі наявні пристрої та контакти знову" + "Скидайте ідентичність тільки якщо ви не маєте доступу до інших пристроїв в обліковому записі та втратили свій ключ відновлення." + "Якщо ви не увійшли на інших пристроях та втратили свій ключ відновлення, то вам доведеться скинути свою ідентичність, щоб продовжити використовувати застосунок. " + "Скиньте свою ідентичність, якщо не можете підтвердити іншим способом" "Не вдалося вибрати медіафайл, спробуйте ще раз." "Не вдалося обробити медіафайл для завантаження, спробуйте ще раз." "Не вдалося завантажити медіафайл, спробуйте ще раз." + "Так, скинути зараз" + "Цей процес незворотний." + "Ви впевнені, що хочете скинути шифрування?" + "Ввести…" + "Підтвердьте, що ви хочете скинути шифрування." + "Введіть пароль облікового запису, щоб продовжити" "Не вдалося обробити медіафайл для завантаження, спробуйте ще раз." "Не вдалося отримати дані користувача" "Заблокувати" "Заблоковані користувачі не зможуть надсилати Вам повідомлення, і всі їхні повідомлення будуть приховані. Ви можете розблокувати їх у будь-який час." "Заблокувати користувача" + "Профіль" "Розблокувати" "Ви знову зможете бачити всі повідомлення від них." "Розблокувати користувача" + "%1$s із %2$s" + "%1$s Закріплених повідомлень" + "Переглянути всі" + "Чат" "Поділитися розташуванням" "Поділитися моїм розташуванням" "Відкрити в Apple Maps" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index c66d504ea8..ef997755dd 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -260,6 +260,7 @@ Reason: %1$s." "Some messages have not been sent" "Sorry, an error occurred" "The authenticity of this encrypted message can\'t be guaranteed on this device." + "Not encrypted." "Encrypted by an unknown or deleted device." "Encrypted by a device not verified by its owner." "Encrypted by an unverified user." @@ -276,12 +277,20 @@ Reason: %1$s." "Failed selecting media, please try again." "Failed processing media to upload, please try again." "Failed uploading media, please try again." + "Press on a message and choose “%1$s” to include here." + "Pin important messages so that they can be easily discovered" + + "%1$d Pinned message" + "%1$d Pinned messages" + + "Pinned messages" "Yes, reset now" "This process is irreversible." "Are you sure you want to reset your encryption?" "Enter…" "Confirm that you want to reset your encryption." "Enter your account password to continue" + "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" "Block" diff --git a/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_0_de.png b/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_0_de.png index b680ac5200..b731d9654c 100644 --- a/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_0_de.png +++ b/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82cb8a36f3d7dc08104f341c9231b645a1908f902e4badf507581989377159ca -size 53573 +oid sha256:c33d7b5f5c2eb70d8c67f715df11a1dc08f76a5874ec524db3015b56b2e75aaa +size 56141 diff --git a/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_1_de.png b/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_1_de.png index d36ff169e1..e52536f976 100644 --- a/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_1_de.png +++ b/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c031ab911290c1ba76faaf449ef9ff75b2a84ec10164ad7be8d6a6036369bcc7 -size 54561 +oid sha256:80a90ae223b2db6ef8cc9a0b52689c6aaa200753ee5efc782e480262e0c006c8 +size 57088 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_0_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_0_de.png deleted file mode 100644 index 049e5856f0..0000000000 --- a/screenshots/de/features.messages.impl_MessagesView_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5fe0f0f74ddcfb738c2b9e713df22db6ef6cba28ac0f885899b83f2b9fde5620 -size 55515 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png index 119ce31df4..17746c958b 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:534fafc31674c6ef6f2b8cd36de9d7e6c2b241c8bd1ce96b89b610049e828177 -size 58047 +oid sha256:8eaaf78856243a79ca9a690d5086c7150364628546ede56372fafbbc7f3d67d1 +size 59309 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png index 8eb6aa0fb2..9ef066335c 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81e572a32a20e8c261e9d42a36dc3bcb70d5aa04ef743e8a03a337f1b082a3eb -size 45887 +oid sha256:57e4e00d2044083e4c851fe39a4be5da0fa9d54f535a4b8a47ed67abfb8299cf +size 47084 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_12_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_12_de.png deleted file mode 100644 index e61b55b743..0000000000 --- a/screenshots/de/features.messages.impl_MessagesView_Day_12_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a580cba9e5b9c210196b961e47733b213fdcb9dff7c2198c86689a0213e76494 -size 55553 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png index e1534ddfb9..d448b125bb 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a38ed5dfdf050c8084c8982ff068e1330ac2f3c4f4790678e1508c78214c45bb -size 56773 +oid sha256:ae733c65e0ebe554e6741b48f5b5b2c06fd05e4380b37cdaa827b07349d7951d +size 59978 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png index a3c82d2c02..20fe3cecf5 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb47deea5a5883aba4428915b00d523e80315bbf1fcecc727f1568b6b925cdde -size 53538 +oid sha256:9a886fb07d1866fc6d0be8ac34cbac05930e98f8a994d666f87c2c9a4b01cb20 +size 54707 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_5_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_5_de.png deleted file mode 100644 index f2daa47e63..0000000000 --- a/screenshots/de/features.messages.impl_MessagesView_Day_5_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:69b89fb9b9a6cac6d39f7c90e5c31500df005b878de60e2311eeb51d42daea90 -size 53339 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png index 3ae9773013..67b3c9dce1 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b76d6e2b03d78d7fe4a863cc8c086f7f09a93b574ee8308a00a92af4f7665e2c -size 53187 +oid sha256:66d6532d4d0ca266c26260ffbdd69f9957743c11f3a5fd2cae118892f119f0b6 +size 53881 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png index 5ae9252218..3143574e3f 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16cc141367a4631a5b5aa17f7373e52b330f87f74b936e58befc0aef79f0468d -size 57582 +oid sha256:290669083f6b2ab605ccd5721f19052fcefacadaeeaaeed79439d9fcd3db14a1 +size 58696 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png index f057d78f19..0488159920 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:587551bf2aa184b10f9ccd3c8a4cb2e1173c7d2e18021caa6e23329d8db078ac -size 40331 +oid sha256:6869c19d03e795dcefc8056cdd267d24669ee8893394ab90b3952fccb7847bf4 +size 41557 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png index c7d3b5b1d7..67e2d5e9e0 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9db9c664487feca9f1a9e7a3a2ae2cd19129a9aa4b7fc85f8ea534af21f3adc -size 39591 +oid sha256:bd6b605f377925ca0d0511e9d8a03c83aa00ff1236537577f32c4de0521ef57c +size 40841 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 99ccf2796d..0545934f70 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,40 +1,40 @@ // 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",19937,], -["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19937,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19944,], +["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19944,], ["features.invite.impl.response_AcceptDeclineInviteView_Day_0_en","features.invite.impl.response_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19937,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19937,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19937,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19937,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19944,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19944,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19944,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19944,], ["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_4_en","features.login.impl.accountprovider_AccountProviderView_Night_4_en",0,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19937,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19937,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19937,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19937,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19937,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19937,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19937,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19937,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19937,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19937,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19937,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19937,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19944,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19944,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19944,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19944,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19944,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19944,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19944,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19944,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19944,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19944,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19944,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19944,], ["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",19937,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",19944,], ["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",19937,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",19944,], ["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",19937,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",19944,], ["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",19937,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19944,], ["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,], @@ -44,11 +44,11 @@ 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","",19937,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19937,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19937,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19937,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19937,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",19944,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19944,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19944,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19944,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19944,], ["libraries.designsystem.components.avatar_Avatar_Avatars_0_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_10_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_11_en","",0,], @@ -128,13 +128,13 @@ export const screenshots = [ ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], ["libraries.designsystem.components_BigCheckmark_Day_0_en","libraries.designsystem.components_BigCheckmark_Night_0_en",0,], ["libraries.designsystem.components_BigIcon_Day_0_en","libraries.designsystem.components_BigIcon_Night_0_en",0,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19937,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19937,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19937,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19937,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19937,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19937,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19937,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19944,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19944,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19944,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19944,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19944,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19944,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19944,], ["libraries.designsystem.components_BloomInitials_Day_0_en","libraries.designsystem.components_BloomInitials_Night_0_en",0,], ["libraries.designsystem.components_BloomInitials_Day_1_en","libraries.designsystem.components_BloomInitials_Night_1_en",0,], ["libraries.designsystem.components_BloomInitials_Day_2_en","libraries.designsystem.components_BloomInitials_Night_2_en",0,], @@ -145,84 +145,84 @@ export const screenshots = [ ["libraries.designsystem.components_BloomInitials_Day_7_en","libraries.designsystem.components_BloomInitials_Night_7_en",0,], ["libraries.designsystem.components_Bloom_Day_0_en","libraries.designsystem.components_Bloom_Night_0_en",0,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19937,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19937,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19937,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19937,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19937,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19944,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19944,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19944,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19944,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19944,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_0_en","features.call.impl.ui_CallScreenPipView_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_1_en","features.call.impl.ui_CallScreenPipView_Night_1_en",0,], ["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,], -["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19937,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19937,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19937,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19937,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19937,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19937,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19937,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19937,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19937,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19937,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19937,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19944,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19944,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19944,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19944,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19944,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19944,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19944,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19944,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19944,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19944,], ["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",19937,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19937,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",19944,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19944,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19937,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19944,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], ["libraries.textcomposer.components_ComposerOptionsButton_Day_0_en","libraries.textcomposer.components_ComposerOptionsButton_Night_0_en",0,], ["libraries.designsystem.components.avatar_CompositeAvatar_Avatars_en","",0,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19937,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19937,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19944,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19944,], ["features.preferences.impl.developer.tracing_ConfigureTracingView_Day_0_en","features.preferences.impl.developer.tracing_ConfigureTracingView_Night_0_en",0,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19937,], -["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19937,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19944,], +["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19944,], ["libraries.designsystem.components.dialogs_ConfirmationDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ConfirmationDialog_Day_0_en","libraries.designsystem.components.dialogs_ConfirmationDialog_Night_0_en",0,], ["features.networkmonitor.api.ui_ConnectivityIndicatorView_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicatorView_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19937,], -["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19937,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19937,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19937,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19937,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19937,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19937,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19937,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19937,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19937,], -["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19937,], -["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19937,], -["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19937,], -["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19937,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19937,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19937,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19944,], +["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19944,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19944,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19944,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19944,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19944,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19944,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19944,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19944,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19944,], +["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19944,], +["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19944,], +["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19944,], +["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19944,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19944,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19944,], ["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",19937,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19937,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19937,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",19944,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19944,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19944,], ["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",19937,], -["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19937,], -["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19937,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19937,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19937,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19937,], -["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19937,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",19944,], +["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19944,], +["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19944,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19944,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19944,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19944,], +["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19944,], ["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,], @@ -234,12 +234,12 @@ export const screenshots = [ ["libraries.designsystem.text_DpScale_1_0f__en","",0,], ["libraries.designsystem.text_DpScale_1_5f__en","",0,], ["libraries.designsystem.theme.components_DropdownMenuItem_Menus_en","",0,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19937,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19937,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19937,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19937,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19937,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19937,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19944,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19944,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19944,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19944,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19944,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19944,], ["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,], @@ -249,10 +249,10 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiPicker_Night_0_en",0,], -["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19937,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19937,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19937,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19937,], +["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19944,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19944,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19944,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19944,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], ["libraries.designsystem.theme.components_FilledButtonLargeLowPadding_Buttons_en","",0,], @@ -263,15 +263,15 @@ export const screenshots = [ ["libraries.designsystem.theme.components_FloatingActionButton_Floating Action Buttons_en","",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19937,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19937,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19937,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19944,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19944,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19944,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_0_en","features.messages.impl.forward_ForwardMessagesView_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_1_en","features.messages.impl.forward_ForwardMessagesView_Night_1_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_2_en","features.messages.impl.forward_ForwardMessagesView_Night_2_en",0,], -["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19937,], -["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19937,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19944,], +["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19944,], ["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,], @@ -298,37 +298,37 @@ 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",19937,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",19944,], ["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",19937,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",19944,], ["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",19937,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",19944,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19937,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19944,], ["features.joinroom.impl_JoinRoomView_Day_0_en","features.joinroom.impl_JoinRoomView_Night_0_en",0,], ["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",0,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19937,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19937,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19937,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19937,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19937,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19937,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19937,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19937,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19937,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19944,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19944,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19944,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19944,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19944,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19944,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19944,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19944,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19944,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["libraries.designsystem.components_LabelledOutlinedTextField_Day_0_en","libraries.designsystem.components_LabelledOutlinedTextField_Night_0_en",0,], ["libraries.designsystem.components_LabelledTextField_Day_0_en","libraries.designsystem.components_LabelledTextField_Night_0_en",0,], ["features.leaveroom.api_LeaveRoomView_Day_0_en","features.leaveroom.api_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19937,], -["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19937,], -["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19937,], -["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19937,], -["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19937,], -["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19937,], +["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19944,], +["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19944,], +["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19944,], +["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19944,], +["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19944,], +["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19944,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], @@ -379,28 +379,28 @@ 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",19937,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19937,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19937,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19937,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19944,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19944,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19944,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19944,], ["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",19937,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19937,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19937,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19937,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19937,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19937,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19937,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19937,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19937,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19937,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19937,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19937,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19937,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19937,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19937,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",19944,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19944,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19944,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19944,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19944,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19944,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19944,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19944,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19944,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19944,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19944,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19944,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19944,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19944,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19944,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19937,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19944,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en","libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_0_en","libraries.matrix.ui.components_MatrixUserHeader_Night_0_en",0,], @@ -410,7 +410,7 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_10_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19937,], +["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19944,], ["libraries.mediaviewer.api.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_5_en","",0,], @@ -420,10 +420,10 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_9_en","",0,], ["libraries.designsystem.theme.components_MediumTopAppBar_App Bars_en","",0,], ["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,], -["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19937,], +["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19944,], ["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",19937,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",19944,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_10_en","features.messages.impl.timeline.components_MessageEventBubble_Night_10_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_11_en","features.messages.impl.timeline.components_MessageEventBubble_Night_11_en",0,], @@ -447,26 +447,26 @@ 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.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19937,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19937,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19944,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19944,], ["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",0,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19937,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19937,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19937,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19937,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",0,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19944,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19944,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",0,], ["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",0,], ["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",0,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19937,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19937,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19937,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19937,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19937,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19937,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19937,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19937,], -["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19937,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19944,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19944,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19944,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",0,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19944,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19944,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19944,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19944,], +["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19944,], ["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",19937,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",19944,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -475,28 +475,28 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple selection List item - selection in trailing content_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple selection List item - selection in supporting text_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple selection List item - no selection_List items_en","",0,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19937,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19937,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19937,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19944,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19944,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19944,], ["features.login.impl.oidc.webview_OidcView_Day_0_en","features.login.impl.oidc.webview_OidcView_Night_0_en",0,], ["features.login.impl.oidc.webview_OidcView_Day_1_en","features.login.impl.oidc.webview_OidcView_Night_1_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19937,], -["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19937,], -["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19937,], -["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19937,], -["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19937,], +["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19944,], +["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19944,], +["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19944,], +["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19944,], +["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19944,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], @@ -511,53 +511,57 @@ export const screenshots = [ ["libraries.designsystem.components_PageTitleWithIconFull_Day_3_en","libraries.designsystem.components_PageTitleWithIconFull_Night_3_en",0,], ["libraries.designsystem.components_PageTitleWithIconFull_Day_4_en","libraries.designsystem.components_PageTitleWithIconFull_Night_4_en",0,], ["libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en","libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en",0,], -["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19937,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19937,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19937,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19937,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19937,], +["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19944,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19944,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19944,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19944,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19944,], ["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",19937,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19937,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19937,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19944,], ["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_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",0,], ["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",0,], ["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",0,], ["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",0,], ["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",0,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",0,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",0,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",0,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",0,], ["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",19937,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19937,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19937,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19937,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19937,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19944,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19944,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19944,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19944,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19944,], ["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",19937,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19937,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19937,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19937,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19937,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19937,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19937,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19937,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19937,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19937,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19937,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",19944,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19944,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19944,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19944,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19944,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19944,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19944,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19944,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19944,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19944,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19944,], ["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceDivider_Preferences_en","",0,], @@ -573,182 +577,182 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceTextLight_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19937,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19937,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19937,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19937,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19944,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19944,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19944,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19944,], ["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","",19937,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19937,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19937,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19937,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19937,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19937,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19937,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19937,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19937,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19937,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19937,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19937,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19937,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19937,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19937,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19937,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19937,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19937,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",19944,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19944,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19944,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19944,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19944,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19944,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19944,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19944,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19944,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19944,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19944,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19944,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19944,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19944,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19944,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19944,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19944,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19944,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19937,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19937,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19944,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19944,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19937,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19937,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19937,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19937,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19937,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19937,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19937,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19944,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19944,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19944,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19944,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19944,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19944,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19944,], ["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",19937,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19937,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19937,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19937,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19937,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19937,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19937,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19937,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19937,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19937,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19937,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19937,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19937,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19937,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19937,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19937,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19944,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19944,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19944,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19944,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19944,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19944,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19944,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19944,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19944,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19944,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19944,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19944,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19944,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19944,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19944,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19944,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19937,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19944,], ["features.roomdetails.impl.components_RoomBadgeNegative_Day_0_en","features.roomdetails.impl.components_RoomBadgeNegative_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgeNeutral_Day_0_en","features.roomdetails.impl.components_RoomBadgeNeutral_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgePositive_Day_0_en","features.roomdetails.impl.components_RoomBadgePositive_Night_0_en",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",19937,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",19937,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19937,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19937,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19937,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19937,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19937,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19937,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19937,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19937,], -["features.roomdetails.impl_RoomDetails_0_en","",19937,], -["features.roomdetails.impl_RoomDetails_10_en","",19937,], -["features.roomdetails.impl_RoomDetails_11_en","",19937,], -["features.roomdetails.impl_RoomDetails_12_en","",19937,], -["features.roomdetails.impl_RoomDetails_1_en","",19937,], -["features.roomdetails.impl_RoomDetails_2_en","",19937,], -["features.roomdetails.impl_RoomDetails_3_en","",19937,], -["features.roomdetails.impl_RoomDetails_4_en","",19937,], -["features.roomdetails.impl_RoomDetails_5_en","",19937,], -["features.roomdetails.impl_RoomDetails_6_en","",19937,], -["features.roomdetails.impl_RoomDetails_7_en","",19937,], -["features.roomdetails.impl_RoomDetails_8_en","",19937,], -["features.roomdetails.impl_RoomDetails_9_en","",19937,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19937,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19937,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19937,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19937,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19937,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19937,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19937,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19937,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19937,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19937,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19937,], -["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19937,], -["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19937,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",19944,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",19944,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19944,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19944,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19944,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19944,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19944,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19944,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19944,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19944,], +["features.roomdetails.impl_RoomDetails_0_en","",19944,], +["features.roomdetails.impl_RoomDetails_10_en","",19944,], +["features.roomdetails.impl_RoomDetails_11_en","",19944,], +["features.roomdetails.impl_RoomDetails_12_en","",19944,], +["features.roomdetails.impl_RoomDetails_1_en","",19944,], +["features.roomdetails.impl_RoomDetails_2_en","",19944,], +["features.roomdetails.impl_RoomDetails_3_en","",19944,], +["features.roomdetails.impl_RoomDetails_4_en","",19944,], +["features.roomdetails.impl_RoomDetails_5_en","",19944,], +["features.roomdetails.impl_RoomDetails_6_en","",19944,], +["features.roomdetails.impl_RoomDetails_7_en","",19944,], +["features.roomdetails.impl_RoomDetails_8_en","",19944,], +["features.roomdetails.impl_RoomDetails_9_en","",19944,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19944,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19944,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19944,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19944,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19944,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19944,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19944,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19944,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19944,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19944,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19944,], +["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19944,], +["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19944,], ["features.roomlist.impl.components_RoomListContentView_Day_2_en","features.roomlist.impl.components_RoomListContentView_Night_2_en",0,], -["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19937,], -["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19937,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19937,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19937,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19937,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19937,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19937,], +["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19944,], +["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19944,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19944,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19944,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19944,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19944,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19944,], ["features.roomlist.impl.search_RoomListSearchContent_Day_0_en","features.roomlist.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19937,], -["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19937,], -["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19937,], +["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19944,], +["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19944,], +["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19944,], ["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",0,], -["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19937,], -["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19937,], -["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19937,], -["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19937,], -["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19937,], -["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19937,], -["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19937,], +["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19944,], +["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19944,], +["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19944,], +["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19944,], +["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19944,], +["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19944,], +["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19944,], ["features.roomlist.impl_RoomListView_Day_8_en","features.roomlist.impl_RoomListView_Night_8_en",0,], -["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19937,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19937,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19937,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19937,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19937,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19937,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19937,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19937,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19937,], +["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19944,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19944,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19944,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19944,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19944,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19944,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19944,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19944,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19944,], ["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19937,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19937,], -["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19937,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19944,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19944,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19944,], ["libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Day_0_en","libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Night_0_en",0,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19937,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19937,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19937,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19937,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19937,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19937,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19937,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19937,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19937,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19944,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19944,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19944,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19944,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19944,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19944,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19944,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19944,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19944,], ["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_9_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19937,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19937,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19937,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19937,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19937,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19937,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19937,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19937,], -["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19937,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19937,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19937,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19937,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19937,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19937,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19937,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19944,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19944,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19944,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19944,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19944,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19944,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19944,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19944,], +["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19944,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19944,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19944,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19944,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19944,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19944,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19944,], ["features.roomlist.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.roomlist.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_0_en","features.roomlist.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_10_en","features.roomlist.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -771,10 +775,10 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_26_en","features.roomlist.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_27_en","features.roomlist.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_28_en","features.roomlist.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19937,], -["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19937,], -["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19937,], -["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19937,], +["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19944,], +["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19944,], +["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19944,], +["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19944,], ["features.roomlist.impl.components_RoomSummaryRow_Day_3_en","features.roomlist.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_4_en","features.roomlist.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_5_en","features.roomlist.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -782,64 +786,64 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_7_en","features.roomlist.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_8_en","features.roomlist.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_9_en","features.roomlist.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19937,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19937,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19937,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19944,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19944,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19944,], ["appicon.element_RoundIcon_en","",0,], ["appicon.enterprise_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",19937,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19937,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19937,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",19944,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19944,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19944,], ["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","",19937,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search views_en","",19944,], ["libraries.designsystem.theme.components_SearchBarActiveWithQueryNoBackButton_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithQuery_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarInactive_Search views_en","",0,], -["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19937,], -["features.createroom.impl.components_SearchSingleUserResultItem_en","",19937,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19937,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19937,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19937,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19937,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19937,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19937,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19937,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19937,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19937,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19937,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19937,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19937,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19937,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19937,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19937,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19937,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19937,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19937,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19937,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19937,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19937,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19937,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19937,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19937,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19937,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19937,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19937,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19937,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19937,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19937,], +["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19944,], +["features.createroom.impl.components_SearchSingleUserResultItem_en","",19944,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19944,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19944,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19944,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19944,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19944,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19944,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19944,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19944,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19944,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19944,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19944,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19944,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19944,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19944,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19944,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19944,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19944,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19944,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19944,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19944,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19944,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19944,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19944,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19944,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19944,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19944,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19944,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19944,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19944,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19944,], ["libraries.matrix.ui.components_SelectedRoom_Day_0_en","libraries.matrix.ui.components_SelectedRoom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoom_Day_1_en","libraries.matrix.ui.components_SelectedRoom_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en","libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUser_Day_0_en","libraries.matrix.ui.components_SelectedUser_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19937,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19937,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19937,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19937,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19937,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19944,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19944,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19944,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19944,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19944,], ["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,], @@ -849,37 +853,37 @@ 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.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19937,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19937,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19937,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19937,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19937,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19937,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19944,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19944,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19944,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19944,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19944,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19944,], ["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",19937,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",19944,], ["features.messages.impl.timeline.components.reactionsummary_SheetContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_SheetContent_Night_0_en",0,], ["features.messages.impl.actionlist_SheetContent_Day_0_en","features.messages.impl.actionlist_SheetContent_Night_0_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19937,], +["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19944,], ["features.messages.impl.actionlist_SheetContent_Day_1_en","features.messages.impl.actionlist_SheetContent_Night_1_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19937,], -["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19937,], -["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19937,], -["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19937,], -["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19937,], -["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19937,], -["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19937,], -["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19937,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19937,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19937,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19937,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19937,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19937,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19937,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19937,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19937,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19937,], +["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19944,], +["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19944,], +["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19944,], +["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19944,], +["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19944,], +["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19944,], +["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19944,], +["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19944,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19944,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19944,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19944,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19944,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19944,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19944,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19944,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19944,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19944,], ["libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en",0,], ["libraries.designsystem.components.list_SingleSelectionListItemCustomFormattert_Single selection List item - custom formatter_List items_en","",0,], @@ -888,7 +892,7 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single selection List item - no selection, supporting text_List items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single selection List item - no selection_List items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19937,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19944,], ["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,], @@ -898,36 +902,36 @@ export const screenshots = [ ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], ["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",0,], -["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19937,], +["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19944,], ["features.location.api_StaticMapView_Day_0_en","features.location.api_StaticMapView_Night_0_en",0,], ["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",19937,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",19944,], ["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_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19937,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19937,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19937,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19937,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19937,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19937,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19937,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19944,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19944,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19944,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19944,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19944,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19944,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19944,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], ["libraries.designsystem.theme.components_TextFieldDark_TextFields_en","",0,], @@ -939,38 +943,38 @@ export const screenshots = [ ["libraries.designsystem.theme.components_TextFieldValueTextFieldDark_TextFields_en","",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19937,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19937,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19937,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19944,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19944,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19944,], ["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",19937,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19937,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",19944,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19944,], ["features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en",0,], ["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_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19937,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19944,], ["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",19937,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19937,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19937,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",19944,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19944,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19944,], ["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,], ["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",19937,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19937,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19937,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19944,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19944,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19944,], ["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",19937,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19937,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",19944,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19944,], ["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,], @@ -979,36 +983,36 @@ 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",19937,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19944,], ["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",19937,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19944,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19937,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19944,], ["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_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19937,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19937,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19944,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19944,], ["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_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",19937,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",19944,], ["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",19937,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19937,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19937,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19937,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19937,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19944,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19944,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19944,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19944,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19944,], ["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",19937,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19937,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",19944,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19944,], ["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",19937,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",19944,], ["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,], @@ -1017,8 +1021,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",19937,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19937,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",19944,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19944,], ["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,], @@ -1030,7 +1034,7 @@ 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",19937,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",19944,], ["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,], @@ -1052,79 +1056,79 @@ 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_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19937,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19944,], ["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",19937,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19937,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19937,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19937,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19937,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19937,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19937,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19944,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19944,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19944,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19944,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19944,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19944,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19944,], ["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",19937,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",19944,], ["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",19937,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",19944,], ["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",19937,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",19944,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.theme.components_TopAppBar_App Bars_en","",0,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19937,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19937,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19937,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19937,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19937,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19937,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19937,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19937,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19944,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19944,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19944,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19944,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19944,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19944,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19944,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19944,], ["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",19937,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19937,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19937,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19937,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19937,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19937,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",19944,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19944,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19944,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19944,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19944,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19944,], ["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","",19937,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",19944,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19937,], -["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19937,], -["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19937,], -["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19937,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19944,], +["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19944,], +["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19944,], +["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19944,], ["features.createroom.impl.components_UserListView_Day_3_en","features.createroom.impl.components_UserListView_Night_3_en",0,], ["features.createroom.impl.components_UserListView_Day_4_en","features.createroom.impl.components_UserListView_Night_4_en",0,], ["features.createroom.impl.components_UserListView_Day_5_en","features.createroom.impl.components_UserListView_Night_5_en",0,], ["features.createroom.impl.components_UserListView_Day_6_en","features.createroom.impl.components_UserListView_Night_6_en",0,], -["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19937,], +["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19944,], ["features.createroom.impl.components_UserListView_Day_8_en","features.createroom.impl.components_UserListView_Night_8_en",0,], -["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19937,], +["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19944,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], ["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",0,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19937,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19937,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19937,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19937,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19937,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19937,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19937,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19937,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19937,], -["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19937,], -["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19937,], -["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19937,], -["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19937,], -["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19937,], -["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19937,], -["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19937,], -["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19937,], -["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19937,], -["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19937,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19944,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19944,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19944,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19944,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19944,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19944,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19944,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19944,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19944,], +["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19944,], +["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19944,], +["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19944,], +["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19944,], +["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19944,], +["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19944,], +["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19944,], +["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19944,], +["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19944,], +["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19944,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,], @@ -1138,12 +1142,12 @@ export const screenshots = [ ["libraries.textcomposer.components_VoiceMessageRecorderButton_Day_0_en","libraries.textcomposer.components_VoiceMessageRecorderButton_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessageRecording_Day_0_en","libraries.textcomposer.components_VoiceMessageRecording_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessage_Day_0_en","libraries.textcomposer.components_VoiceMessage_Night_0_en",0,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19937,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19937,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19937,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19937,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19937,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19944,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19944,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19944,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19944,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19944,], ["libraries.designsystem.components.media_WaveformPlaybackView_Day_0_en","libraries.designsystem.components.media_WaveformPlaybackView_Night_0_en",0,], -["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19937,], +["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19944,], ["libraries.designsystem.ruler_WithRulers_Day_0_en","libraries.designsystem.ruler_WithRulers_Night_0_en",0,], ]; From 683f26c051a1d70e0d64f74a0fd809f53c4730b1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 12 Aug 2024 14:16:58 +0200 Subject: [PATCH 093/186] Ensure sessionPath is not reused for different homeserver. --- .../auth/RustMatrixAuthenticationService.kt | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) 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 e1ff0811e1..4408f59cd9 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 @@ -60,7 +60,7 @@ import javax.inject.Inject @ContributesBinding(AppScope::class) @SingleIn(AppScope::class) class RustMatrixAuthenticationService @Inject constructor( - baseDirectory: File, + private val baseDirectory: File, private val coroutineDispatchers: CoroutineDispatchers, private val sessionStore: SessionStore, private val rustMatrixClientFactory: RustMatrixClientFactory, @@ -70,10 +70,18 @@ class RustMatrixAuthenticationService @Inject constructor( // Passphrase which will be used for new sessions. Existing sessions will use the passphrase // stored in the SessionData. private val pendingPassphrase = getDatabasePassphrase() - private val sessionPath = File(baseDirectory, UUID.randomUUID().toString()).absolutePath + // Need to keep a copy of the current session path to delete it. + // Ideally it would be possible to get the sessionPath from the Client to avoid doing this. + private var sessionPath: File? = null private var currentClient: Client? = null private var currentHomeserver = MutableStateFlow(null) + private fun rotateSessionPath(): File { + sessionPath?.deleteRecursively() + return File(baseDirectory, UUID.randomUUID().toString()) + .also { sessionPath = it } + } + override fun loggedInStateFlow(): Flow { return sessionStore.isLoggedIn() } @@ -117,8 +125,9 @@ class RustMatrixAuthenticationService @Inject constructor( override suspend fun setHomeserver(homeserver: String): Result = withContext(coroutineDispatchers.io) { + val emptySessionPath = rotateSessionPath() runCatching { - val client = getBaseClientBuilder() + val client = getBaseClientBuilder(emptySessionPath) .serverNameOrHomeserverUrl(homeserver) .build() currentClient = client @@ -135,13 +144,14 @@ class RustMatrixAuthenticationService @Inject constructor( withContext(coroutineDispatchers.io) { runCatching { val client = currentClient ?: error("You need to call `setHomeserver()` first") + val currentSessionPath = sessionPath ?: error("You need to call `setHomeserver()` first") client.login(username, password, "Element X Android", null) val sessionData = client.session() .toSessionData( isTokenValid = true, loginType = LoginType.PASSWORD, passphrase = pendingPassphrase, - sessionPath = sessionPath, + sessionPath = currentSessionPath.absolutePath, ) clear() sessionStore.storeData(sessionData) @@ -185,13 +195,14 @@ class RustMatrixAuthenticationService @Inject constructor( return withContext(coroutineDispatchers.io) { runCatching { val client = currentClient ?: error("You need to call `setHomeserver()` first") + val currentSessionPath = sessionPath ?: error("You need to call `setHomeserver()` first") val urlForOidcLogin = pendingOidcAuthorizationData ?: error("You need to call `getOidcUrl()` first") client.loginWithOidcCallback(urlForOidcLogin, callbackUrl) val sessionData = client.session().toSessionData( isTokenValid = true, loginType = LoginType.OIDC, passphrase = pendingPassphrase, - sessionPath = sessionPath, + sessionPath = currentSessionPath.absolutePath, ) clear() pendingOidcAuthorizationData?.close() @@ -206,9 +217,10 @@ class RustMatrixAuthenticationService @Inject constructor( override suspend fun loginWithQrCode(qrCodeData: MatrixQrCodeLoginData, progress: (QrCodeLoginStep) -> Unit) = withContext(coroutineDispatchers.io) { + val emptySessionPath = rotateSessionPath() runCatching { val client = rustMatrixClientFactory.getBaseClientBuilder( - sessionPath = sessionPath, + sessionPath = emptySessionPath.absolutePath, passphrase = pendingPassphrase, slidingSyncProxy = AuthenticationConfig.SLIDING_SYNC_PROXY_URL, slidingSync = ClientBuilderSlidingSync.Discovered, @@ -229,7 +241,7 @@ class RustMatrixAuthenticationService @Inject constructor( isTokenValid = true, loginType = LoginType.QR, passphrase = pendingPassphrase, - sessionPath = sessionPath, + sessionPath = emptySessionPath.absolutePath, ) sessionStore.storeData(sessionData) SessionId(sessionData.userId) @@ -246,11 +258,13 @@ class RustMatrixAuthenticationService @Inject constructor( } Timber.e(throwable, "Failed to login with QR code") } - } + } - private fun getBaseClientBuilder() = rustMatrixClientFactory + private fun getBaseClientBuilder( + sessionPath: File, + ) = rustMatrixClientFactory .getBaseClientBuilder( - sessionPath = sessionPath, + sessionPath = sessionPath.absolutePath, passphrase = pendingPassphrase, slidingSyncProxy = AuthenticationConfig.SLIDING_SYNC_PROXY_URL, slidingSync = ClientBuilderSlidingSync.Discovered, From 01ece74343a95cce9805bfd7932d3a90f6c9d460 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 12 Aug 2024 14:55:12 +0200 Subject: [PATCH 094/186] Fix formatting and improve comment. --- .../matrix/impl/auth/RustMatrixAuthenticationService.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 4408f59cd9..b447dd584b 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 @@ -70,7 +70,8 @@ class RustMatrixAuthenticationService @Inject constructor( // Passphrase which will be used for new sessions. Existing sessions will use the passphrase // stored in the SessionData. private val pendingPassphrase = getDatabasePassphrase() - // Need to keep a copy of the current session path to delete it. + + // Need to keep a copy of the current session path to eventually delete it. // Ideally it would be possible to get the sessionPath from the Client to avoid doing this. private var sessionPath: File? = null private var currentClient: Client? = null From 4ab0b1074d69e85126d5fcbd914f8d35db5b3af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 7 Aug 2024 12:59:57 +0200 Subject: [PATCH 095/186] Initial implementation of the reset identity feature --- .../FtueSessionVerificationFlowNode.kt | 17 ++ .../api/SecureBackupEntryPoint.kt | 3 + .../securebackup/impl/SecureBackupFlowNode.kt | 15 +- .../impl/reset/ResetIdentityFlowManager.kt | 79 +++++++++ .../impl/reset/ResetIdentityFlowNode.kt | 127 +++++++++++++++ .../reset/password/ResetKeyPasswordEvent.kt | 22 +++ .../reset/password/ResetKeyPasswordNode.kt | 55 +++++++ .../password/ResetKeyPasswordPresenter.kt | 60 +++++++ .../reset/password/ResetKeyPasswordState.kt | 24 +++ .../reset/password/ResetKeyPasswordView.kt | 120 ++++++++++++++ .../impl/reset/root/ResetKeyRootEvent.kt | 22 +++ .../impl/reset/root/ResetKeyRootNode.kt | 50 ++++++ .../impl/reset/root/ResetKeyRootPresenter.kt | 43 +++++ .../impl/reset/root/ResetKeyRootState.kt | 22 +++ .../reset/root/ResetKeyRootStateProvider.kt | 33 ++++ .../impl/reset/root/ResetKeyRootView.kt | 149 +++++++++++++++++ .../api/VerifySessionEntryPoint.kt | 1 + .../impl/VerifySelfSessionNode.kt | 1 + .../impl/VerifySelfSessionView.kt | 154 ++++++++++-------- .../libraries/matrix/api/MatrixClient.kt | 1 + .../api/encryption/EncryptionService.kt | 14 ++ .../impl/encryption/RustEncryptionService.kt | 5 + .../encryption/RustIdentityResetHandle.kt | 54 ++++++ 23 files changed, 1003 insertions(+), 68 deletions(-) create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordEvent.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordNode.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordPresenter.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordState.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordView.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootEvent.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootNode.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootPresenter.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootState.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootStateProvider.kt create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootView.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/FtueSessionVerificationFlowNode.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/FtueSessionVerificationFlowNode.kt index a5dc840267..3e4ed218a5 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/FtueSessionVerificationFlowNode.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/FtueSessionVerificationFlowNode.kt @@ -58,6 +58,9 @@ class FtueSessionVerificationFlowNode @AssistedInject constructor( @Parcelize data object EnterRecoveryKey : NavTarget + + @Parcelize + data object ResetIdentity : NavTarget } interface Callback : Plugin { @@ -85,6 +88,10 @@ class FtueSessionVerificationFlowNode @AssistedInject constructor( override fun onDone() { plugins().forEach { it.onDone() } } + + override fun onResetKey() { + backstack.push(NavTarget.ResetIdentity) + } }) .build() } @@ -94,6 +101,16 @@ class FtueSessionVerificationFlowNode @AssistedInject constructor( .callback(secureBackupEntryPointCallback) .build() } + is NavTarget.ResetIdentity -> { + secureBackupEntryPoint.nodeBuilder(this, buildContext) + .params(SecureBackupEntryPoint.Params(SecureBackupEntryPoint.InitialTarget.ResetIdentity)) + .callback(object : SecureBackupEntryPoint.Callback { + override fun onDone() { + plugins().forEach { it.onDone() } + } + }) + .build() + } } } diff --git a/features/securebackup/api/src/main/kotlin/io/element/android/features/securebackup/api/SecureBackupEntryPoint.kt b/features/securebackup/api/src/main/kotlin/io/element/android/features/securebackup/api/SecureBackupEntryPoint.kt index 45e3a75738..416ecff1bc 100644 --- a/features/securebackup/api/src/main/kotlin/io/element/android/features/securebackup/api/SecureBackupEntryPoint.kt +++ b/features/securebackup/api/src/main/kotlin/io/element/android/features/securebackup/api/SecureBackupEntryPoint.kt @@ -34,6 +34,9 @@ interface SecureBackupEntryPoint : FeatureEntryPoint { @Parcelize data object CreateNewRecoveryKey : InitialTarget + + @Parcelize + data object ResetIdentity : InitialTarget } data class Params(val initialElement: InitialTarget) : NodeInputs diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt index f54bfaee96..d741eb11a7 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt @@ -34,6 +34,7 @@ import io.element.android.features.securebackup.impl.createkey.CreateNewRecovery import io.element.android.features.securebackup.impl.disable.SecureBackupDisableNode import io.element.android.features.securebackup.impl.enable.SecureBackupEnableNode import io.element.android.features.securebackup.impl.enter.SecureBackupEnterRecoveryKeyNode +import io.element.android.features.securebackup.impl.reset.ResetIdentityFlowNode import io.element.android.features.securebackup.impl.root.SecureBackupRootNode import io.element.android.features.securebackup.impl.setup.SecureBackupSetupNode import io.element.android.libraries.architecture.BackstackView @@ -48,10 +49,11 @@ class SecureBackupFlowNode @AssistedInject constructor( @Assisted plugins: List, ) : BaseFlowNode( backstack = BackStack( - initialElement = when (plugins.filterIsInstance(SecureBackupEntryPoint.Params::class.java).first().initialElement) { + initialElement = when (plugins.filterIsInstance().first().initialElement) { SecureBackupEntryPoint.InitialTarget.Root -> NavTarget.Root SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey -> NavTarget.EnterRecoveryKey SecureBackupEntryPoint.InitialTarget.CreateNewRecoveryKey -> NavTarget.CreateNewRecoveryKey + is SecureBackupEntryPoint.InitialTarget.ResetIdentity -> NavTarget.ResetIdentity }, savedStateMap = buildContext.savedStateMap, ), @@ -79,6 +81,9 @@ class SecureBackupFlowNode @AssistedInject constructor( @Parcelize data object CreateNewRecoveryKey : NavTarget + + @Parcelize + data object ResetIdentity : NavTarget } private val callbacks = plugins() @@ -146,6 +151,14 @@ class SecureBackupFlowNode @AssistedInject constructor( NavTarget.CreateNewRecoveryKey -> { createNode(buildContext) } + is NavTarget.ResetIdentity -> { + val callback = object : ResetIdentityFlowNode.Callback { + override fun onDone() { + callbacks.forEach { it.onDone() } + } + } + createNode(buildContext, listOf(callback)) + } } } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt new file mode 100644 index 0000000000..76674cd87d --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset + +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.di.SingleIn +import io.element.android.libraries.di.annotations.SessionCoroutineScope +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle +import io.element.android.libraries.matrix.api.verification.SessionVerificationService +import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterIsInstance +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch +import javax.inject.Inject + +class ResetIdentityFlowManager @Inject constructor( + private val matrixClient: MatrixClient, + @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, + private val sessionVerificationService: SessionVerificationService, +) { + private val resetHandleFlow: MutableStateFlow> = MutableStateFlow(AsyncData.Uninitialized) + val currentHandleFlow: StateFlow> = resetHandleFlow + + fun whenResetIsDone(block: () -> Unit) { + sessionCoroutineScope.launch { + sessionVerificationService.sessionVerifiedStatus.filterIsInstance().first() + block() + } + } + + fun currentSessionId(): SessionId { + return matrixClient.sessionId + } + + fun getResetHandle(): StateFlow> { + return if (resetHandleFlow.value.isLoading() || resetHandleFlow.value.isSuccess()) { + resetHandleFlow + } else { + resetHandleFlow.value = AsyncData.Loading() + + sessionCoroutineScope.launch { + matrixClient.encryptionService().startIdentityReset() + .onSuccess { handle -> + resetHandleFlow.value = if (handle != null) { + AsyncData.Success(handle) + } else { + AsyncData.Failure(IllegalStateException("Could not get a reset identity handle")) + } + } + .onFailure { resetHandleFlow.value = AsyncData.Failure(it) } + } + + resetHandleFlow + } + } +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt new file mode 100644 index 0000000000..a7c0011625 --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset + +import android.app.Activity +import android.os.Parcelable +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.bumble.appyx.core.plugin.plugins +import com.bumble.appyx.navmodel.backstack.BackStack +import com.bumble.appyx.navmodel.backstack.operation.push +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.securebackup.impl.reset.password.ResetKeyPasswordNode +import io.element.android.features.securebackup.impl.reset.root.ResetKeyRootNode +import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.architecture.BackstackView +import io.element.android.libraries.architecture.BaseFlowNode +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle +import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle +import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.filterIsInstance +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import kotlinx.parcelize.Parcelize + +@ContributesNode(SessionScope::class) +class ResetIdentityFlowNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val resetIdentityFlowManager: ResetIdentityFlowManager, + private val coroutineScope: CoroutineScope, +) : BaseFlowNode( + backstack = BackStack(initialElement = NavTarget.Root, savedStateMap = buildContext.savedStateMap), + buildContext = buildContext, + plugins = plugins, +) { + interface Callback: Plugin { + fun onDone() + } + + sealed interface NavTarget : Parcelable { + @Parcelize + data object Root : NavTarget + + @Parcelize + data object ResetPassword : NavTarget + +// @Parcelize +// data class ResetOidc(val url: String) : NavTarget + } + + private lateinit var activity: Activity + + override fun onBuilt() { + super.onBuilt() + + resetIdentityFlowManager.whenResetIsDone { + plugins().forEach { it.onDone() } + } + } + + override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { + return when (navTarget) { + is NavTarget.Root -> { + val callback = object : ResetKeyRootNode.Callback { + override fun onContinue() { + coroutineScope.startReset() + } + } + createNode(buildContext, listOf(callback)) + } + is NavTarget.ResetPassword -> { + val handle = resetIdentityFlowManager.currentHandleFlow.value.dataOrNull() as? IdentityPasswordResetHandle ?: error("No password handle found") + createNode( + buildContext, + listOf(ResetKeyPasswordNode.Inputs(resetIdentityFlowManager.currentSessionId(), handle)) + ) + } + } + } + + private fun CoroutineScope.startReset() = launch { + val handle = resetIdentityFlowManager.getResetHandle() + .filterIsInstance>() + .first() + .data + + when (handle) { + is IdentityOidcResetHandle -> { + activity.openUrlInChromeCustomTab(null, false, handle.url) + handle.resetOidc() + } + is IdentityPasswordResetHandle -> backstack.push(NavTarget.ResetPassword) + } + } + + @Composable + override fun View(modifier: Modifier) { + (LocalContext.current as? Activity)?.let { activity = it } + + BackstackView(modifier) + } +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordEvent.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordEvent.kt new file mode 100644 index 0000000000..5fce7cdf85 --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordEvent.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.password + +sealed interface ResetKeyPasswordEvent { + data class Reset(val password: String) : ResetKeyPasswordEvent + data object DismissError : ResetKeyPasswordEvent +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordNode.kt new file mode 100644 index 0000000000..c430bbec28 --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordNode.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.password + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.bumble.appyx.core.plugin.plugins +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle + +@ContributesNode(SessionScope::class) +class ResetKeyPasswordNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, +) : Node(buildContext, plugins = plugins) { + + data class Inputs(val userId: UserId, val handle: IdentityPasswordResetHandle) : NodeInputs + + private val presenter by lazy { + val inputs = inputs() + ResetKeyPasswordPresenter(inputs.userId, inputs.handle) + } + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + ResetKeyPasswordView( + state = state, + onBack = ::navigateUp + ) + } +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordPresenter.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordPresenter.kt new file mode 100644 index 0000000000..19fa002108 --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordPresenter.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.password + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.architecture.runCatchingUpdatingState +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +class ResetKeyPasswordPresenter( + private val userId: UserId, + private val identityPasswordResetHandle: IdentityPasswordResetHandle, +) : Presenter { + @Composable + override fun present(): ResetKeyPasswordState { + val coroutineScope = rememberCoroutineScope() + + val resetAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } + + fun handleEvent(event: ResetKeyPasswordEvent) { + when (event) { + is ResetKeyPasswordEvent.Reset -> coroutineScope.reset(userId, event.password, resetAction) + ResetKeyPasswordEvent.DismissError -> resetAction.value = AsyncAction.Uninitialized + } + } + + return ResetKeyPasswordState( + resetAction = resetAction.value, + eventSink = ::handleEvent + ) + } + + private fun CoroutineScope.reset(userId: UserId, password: String, action: MutableState>) = launch { + suspend { + identityPasswordResetHandle.resetPassword(userId, password).getOrThrow() + }.runCatchingUpdatingState(action) + } +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordState.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordState.kt new file mode 100644 index 0000000000..3de58ec032 --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordState.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.password + +import io.element.android.libraries.architecture.AsyncAction + +data class ResetKeyPasswordState( + val resetAction: AsyncAction, + val eventSink: (ResetKeyPasswordEvent) -> Unit, +) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordView.kt new file mode 100644 index 0000000000..d9339064f2 --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordView.kt @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.password + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage +import io.element.android.libraries.designsystem.components.BigIcon +import io.element.android.libraries.designsystem.components.ProgressDialog +import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog +import io.element.android.libraries.designsystem.components.form.textFieldState +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.IconButton +import io.element.android.libraries.designsystem.theme.components.OutlinedTextField +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun ResetKeyPasswordView( + state: ResetKeyPasswordState, + onBack: () -> Unit, + modifier: Modifier = Modifier, +) { + val passwordState = textFieldState(stateValue = "") + FlowStepPage( + modifier = modifier, + iconStyle = BigIcon.Style.Default(CompoundIcons.LockSolid()), + title = stringResource(CommonStrings.screen_reset_encryption_password_title), + subTitle = stringResource(CommonStrings.screen_reset_encryption_password_subtitle), + onBackClick = onBack, + content = { Content(textFieldState = passwordState) }, + buttons = { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.action_reset_identity), + onClick = { state.eventSink(ResetKeyPasswordEvent.Reset(passwordState.value)) }, + destructive = true, + ) + } + ) + + if (state.resetAction.isLoading() || state.resetAction.isSuccess()) { + ProgressDialog() + } else if (state.resetAction.isFailure()) { + ErrorDialog( + content = stringResource(CommonStrings.error_unknown), + onDismiss = { state.eventSink(ResetKeyPasswordEvent.DismissError) } + ) + } +} + +@Composable +private fun Content(textFieldState: MutableState) { + var showPassword by remember { mutableStateOf(false) } + OutlinedTextField( + modifier = Modifier + .fillMaxWidth() + .onTabOrEnterKeyFocusNext(LocalFocusManager.current), + value = textFieldState.value, + onValueChange = { text -> textFieldState.value = text }, + label = { Text(stringResource(CommonStrings.common_password)) }, + placeholder = { Text(stringResource(CommonStrings.screen_reset_encryption_password_placeholder)) }, + singleLine = true, + visualTransformation = if (showPassword) VisualTransformation.None else PasswordVisualTransformation(), + trailingIcon = { + val image = + if (showPassword) CompoundIcons.VisibilityOn() else CompoundIcons.VisibilityOff() + val description = + if (showPassword) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password) + + IconButton(onClick = { showPassword = !showPassword }) { + Icon(imageVector = image, description) + } + } + ) +} + +@PreviewsDayNight +@Composable +internal fun ResetKeyPasswordViewPreview() { + ElementPreview { + ResetKeyPasswordView( + state = ResetKeyPasswordState( + resetAction = AsyncAction.Uninitialized, + eventSink = {} + ), + onBack = {} + ) + } +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootEvent.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootEvent.kt new file mode 100644 index 0000000000..268228ac8b --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootEvent.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.root + +sealed interface ResetKeyRootEvent { + data object Continue : ResetKeyRootEvent + data object DismissDialog : ResetKeyRootEvent +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootNode.kt new file mode 100644 index 0000000000..b7171aaa7b --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootNode.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.root + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.di.SessionScope + +@ContributesNode(SessionScope::class) +class ResetKeyRootNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, +) : Node(buildContext, plugins = plugins) { + interface Callback : Plugin { + fun onContinue() + } + + private val presenter = ResetKeyRootPresenter() + private val callback: Callback = plugins.filterIsInstance().first() + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + ResetKeyRootView( + state = state, + onContinue = callback::onContinue, + onBack = ::navigateUp, + ) + } +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootPresenter.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootPresenter.kt new file mode 100644 index 0000000000..d2e3e5dc70 --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootPresenter.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.root + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import io.element.android.libraries.architecture.Presenter + +class ResetKeyRootPresenter : Presenter { + @Composable + override fun present(): ResetKeyRootState { + var displayConfirmDialog by remember { mutableStateOf(false) } + + fun handleEvent(event: ResetKeyRootEvent) { + displayConfirmDialog = when (event) { + ResetKeyRootEvent.Continue -> true + ResetKeyRootEvent.DismissDialog -> false + } + } + + return ResetKeyRootState( + displayConfirmationDialog = displayConfirmDialog, + eventSink = ::handleEvent + ) + } +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootState.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootState.kt new file mode 100644 index 0000000000..faaee64040 --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootState.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.root + +data class ResetKeyRootState( + val displayConfirmationDialog: Boolean, + val eventSink: (ResetKeyRootEvent) -> Unit, +) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootStateProvider.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootStateProvider.kt new file mode 100644 index 0000000000..15299fa5ba --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootStateProvider.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.root + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider + +class ResetKeyRootStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + ResetKeyRootState( + displayConfirmationDialog = false, + eventSink = {} + ), + ResetKeyRootState( + displayConfirmationDialog = true, + eventSink = {} + ) + ) +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootView.kt new file mode 100644 index 0000000000..cbeaa1a14e --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootView.kt @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.root + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.designsystem.atomic.organisms.InfoListItem +import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrganism +import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage +import io.element.android.libraries.designsystem.components.BigIcon +import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.persistentListOf + +@Composable +fun ResetKeyRootView( + state: ResetKeyRootState, + onContinue: () -> Unit, + onBack: () -> Unit, +) { + FlowStepPage( + iconStyle = BigIcon.Style.AlertSolid, + title = stringResource(io.element.android.libraries.ui.strings.R.string.screen_encryption_reset_title), + subTitle = stringResource(io.element.android.libraries.ui.strings.R.string.screen_encryption_reset_subtitle), + isScrollable = true, + content = { Content() }, + buttons = { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(id = CommonStrings.action_continue), + onClick = { state.eventSink(ResetKeyRootEvent.Continue) }, + destructive = true, + ) + }, + onBackClick = onBack, + ) + + if (state.displayConfirmationDialog) { + ConfirmationDialog( + title = stringResource(CommonStrings.screen_reset_encryption_confirmation_alert_title), + content = stringResource(CommonStrings.screen_reset_encryption_confirmation_alert_subtitle), + submitText = stringResource(CommonStrings.screen_reset_encryption_confirmation_alert_action), + onSubmitClick = { + state.eventSink(ResetKeyRootEvent.DismissDialog) + onContinue() + }, + destructiveSubmit = true, + onDismiss = { state.eventSink(ResetKeyRootEvent.DismissDialog) } + ) + } +} + +@Composable +private fun Content() { + Column( + modifier = Modifier.padding(top = 8.dp, bottom = 40.dp), + verticalArrangement = Arrangement.spacedBy(24.dp), + ) { + InfoListOrganism( + modifier = Modifier.fillMaxWidth(), + items = persistentListOf( + InfoListItem( + message = stringResource(CommonStrings.screen_encryption_reset_bullet_1), + iconComposable = { + Icon( + modifier = Modifier.size(20.dp), + imageVector = CompoundIcons.Check(), + contentDescription = null, + tint = ElementTheme.colors.iconSuccessPrimary, + ) + }, + ), + InfoListItem( + message = stringResource(CommonStrings.screen_encryption_reset_bullet_2), + iconComposable = { + Icon( + modifier = Modifier.size(20.dp), + imageVector = CompoundIcons.Close(), + contentDescription = null, + tint = ElementTheme.colors.iconCriticalPrimary, + ) + }, + ), + InfoListItem( + message = stringResource(CommonStrings.screen_encryption_reset_bullet_3), + iconComposable = { + Icon( + modifier = Modifier.size(20.dp), + imageVector = CompoundIcons.Close(), + contentDescription = null, + tint = ElementTheme.colors.iconCriticalPrimary, + ) + }, + ), + ), + backgroundColor = ElementTheme.colors.bgActionSecondaryHovered, + ) + + Text( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.screen_encryption_reset_footer), + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textActionPrimary, + textAlign = TextAlign.Center, + ) + } +} + +@PreviewsDayNight +@Composable +internal fun ResetKeyRootViewPreview(@PreviewParameter(ResetKeyRootStateProvider::class) state: ResetKeyRootState) { + ElementPreview { + ResetKeyRootView( + state = state, + onContinue = {}, + onBack = {}, + ) + } +} diff --git a/features/verifysession/api/src/main/kotlin/io/element/android/features/verifysession/api/VerifySessionEntryPoint.kt b/features/verifysession/api/src/main/kotlin/io/element/android/features/verifysession/api/VerifySessionEntryPoint.kt index 8d19ca5698..deb5cdf267 100644 --- a/features/verifysession/api/src/main/kotlin/io/element/android/features/verifysession/api/VerifySessionEntryPoint.kt +++ b/features/verifysession/api/src/main/kotlin/io/element/android/features/verifysession/api/VerifySessionEntryPoint.kt @@ -31,6 +31,7 @@ interface VerifySessionEntryPoint : FeatureEntryPoint { interface Callback : Plugin { fun onEnterRecoveryKey() + fun onResetKey() fun onDone() } } diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionNode.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionNode.kt index 9ce1358683..0ed9524626 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionNode.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionNode.kt @@ -43,6 +43,7 @@ class VerifySelfSessionNode @AssistedInject constructor( state = state, modifier = modifier, onEnterRecoveryKey = callback::onEnterRecoveryKey, + onResetKey = callback::onResetKey, onFinish = callback::onDone, ) } diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt index 6b908e3ebd..f1c169b193 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt @@ -20,6 +20,7 @@ import androidx.activity.compose.BackHandler import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight @@ -53,6 +54,7 @@ import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TopAppBar @@ -66,6 +68,7 @@ import io.element.android.features.verifysession.impl.VerifySelfSessionState.Ver fun VerifySelfSessionView( state: VerifySelfSessionState, onEnterRecoveryKey: () -> Unit, + onResetKey: () -> Unit, onFinish: () -> Unit, modifier: Modifier = Modifier, ) { @@ -115,6 +118,7 @@ fun VerifySelfSessionView( goBack = ::resetFlow, onEnterRecoveryKey = onEnterRecoveryKey, onFinish = onFinish, + onResetKey = onResetKey, ) } ) { @@ -226,6 +230,7 @@ private fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifie private fun BottomMenu( screenState: VerifySelfSessionState, onEnterRecoveryKey: () -> Unit, + onResetKey: () -> Unit, goBack: () -> Unit, onFinish: () -> Unit, ) { @@ -236,42 +241,69 @@ private fun BottomMenu( when (verificationViewState) { is FlowStep.Initial -> { - if (verificationViewState.isLastDevice) { - BottomMenu( - positiveButtonTitle = stringResource(R.string.screen_session_verification_enter_recovery_key), - onPositiveButtonClick = onEnterRecoveryKey, - ) - } else { - BottomMenu( - positiveButtonTitle = stringResource(R.string.screen_identity_use_another_device), - onPositiveButtonClick = { eventSink(VerifySelfSessionViewEvents.RequestVerification) }, - negativeButtonTitle = stringResource(R.string.screen_session_verification_enter_recovery_key), - onNegativeButtonClick = onEnterRecoveryKey, + BottomMenu { + if (verificationViewState.isLastDevice) { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(R.string.screen_session_verification_enter_recovery_key), + onClick = onEnterRecoveryKey, + ) + } else { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(R.string.screen_identity_use_another_device), + onClick = { eventSink(VerifySelfSessionViewEvents.RequestVerification) }, + ) + OutlinedButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(R.string.screen_session_verification_enter_recovery_key), + onClick = onEnterRecoveryKey, + ) + } + TextButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(R.string.screen_identity_confirmation_cannot_confirm), + onClick = onResetKey, ) } } is FlowStep.Canceled -> { - BottomMenu( - positiveButtonTitle = stringResource(R.string.screen_session_verification_positive_button_canceled), - onPositiveButtonClick = { eventSink(VerifySelfSessionViewEvents.RequestVerification) }, - negativeButtonTitle = stringResource(CommonStrings.action_cancel), - onNegativeButtonClick = goBack, - ) + BottomMenu { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(R.string.screen_session_verification_positive_button_canceled), + onClick = { eventSink(VerifySelfSessionViewEvents.RequestVerification) }, + ) + TextButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.action_cancel), + onClick = goBack, + ) + } } is FlowStep.Ready -> { - BottomMenu( - positiveButtonTitle = stringResource(CommonStrings.action_start), - onPositiveButtonClick = { eventSink(VerifySelfSessionViewEvents.StartSasVerification) }, - negativeButtonTitle = stringResource(CommonStrings.action_cancel), - onNegativeButtonClick = goBack, - ) + BottomMenu { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.action_start), + onClick = { eventSink(VerifySelfSessionViewEvents.StartSasVerification) }, + ) + TextButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.action_cancel), + onClick = goBack, + ) + } } is FlowStep.AwaitingOtherDeviceResponse -> { - BottomMenu( - positiveButtonTitle = stringResource(R.string.screen_identity_waiting_on_other_device), - onPositiveButtonClick = {}, - isLoading = true, - ) + BottomMenu { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(R.string.screen_identity_waiting_on_other_device), + onClick = {}, + showProgress = true, + ) + } } is FlowStep.Verifying -> { val positiveButtonTitle = if (isVerifying) { @@ -279,23 +311,32 @@ private fun BottomMenu( } else { stringResource(R.string.screen_session_verification_they_match) } - BottomMenu( - positiveButtonTitle = positiveButtonTitle, - onPositiveButtonClick = { - if (!isVerifying) { - eventSink(VerifySelfSessionViewEvents.ConfirmVerification) - } - }, - negativeButtonTitle = stringResource(R.string.screen_session_verification_they_dont_match), - onNegativeButtonClick = { eventSink(VerifySelfSessionViewEvents.DeclineVerification) }, - isLoading = isVerifying, - ) + BottomMenu { + Button( + modifier = Modifier.fillMaxWidth(), + text = positiveButtonTitle, + showProgress = isVerifying, + onClick = { + if (!isVerifying) { + eventSink(VerifySelfSessionViewEvents.ConfirmVerification) + } + }, + ) + TextButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(R.string.screen_session_verification_they_dont_match), + onClick = { eventSink(VerifySelfSessionViewEvents.DeclineVerification) }, + ) + } } is FlowStep.Completed -> { - BottomMenu( - positiveButtonTitle = stringResource(CommonStrings.action_continue), - onPositiveButtonClick = onFinish, - ) + BottomMenu { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.action_continue), + onClick = onFinish, + ) + } } is FlowStep.Skipped -> return } @@ -303,35 +344,13 @@ private fun BottomMenu( @Composable private fun BottomMenu( - positiveButtonTitle: String?, - onPositiveButtonClick: () -> Unit, modifier: Modifier = Modifier, - negativeButtonTitle: String? = null, - negativeButtonEnabled: Boolean = negativeButtonTitle != null, - onNegativeButtonClick: () -> Unit = {}, - isLoading: Boolean = false, + buttons: @Composable ColumnScope.() -> Unit, ) { ButtonColumnMolecule( modifier = modifier.padding(bottom = 16.dp) ) { - if (positiveButtonTitle != null) { - Button( - text = positiveButtonTitle, - showProgress = isLoading, - modifier = Modifier.fillMaxWidth(), - onClick = onPositiveButtonClick, - ) - } - if (negativeButtonTitle != null) { - TextButton( - text = negativeButtonTitle, - modifier = Modifier.fillMaxWidth(), - onClick = onNegativeButtonClick, - enabled = negativeButtonEnabled, - ) - } else { - Spacer(modifier = Modifier.height(48.dp)) - } + buttons() } } @@ -341,6 +360,7 @@ internal fun VerifySelfSessionViewPreview(@PreviewParameter(VerifySelfSessionSta VerifySelfSessionView( state = state, onEnterRecoveryKey = {}, + onResetKey = {}, onFinish = {}, ) } 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 3209d49e03..0591e794ed 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 @@ -41,6 +41,7 @@ import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService +import io.element.android.libraries.sessionstorage.api.LoginType import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt index f47487c634..fdaebc9c97 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.api.encryption +import io.element.android.libraries.matrix.api.core.UserId import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow @@ -62,4 +63,17 @@ interface EncryptionService { * called the fingerprint of the device. */ suspend fun deviceEd25519(): String? + + suspend fun startIdentityReset(): Result +} + +interface IdentityResetHandle + +interface IdentityPasswordResetHandle : IdentityResetHandle { + suspend fun resetPassword(userId: UserId, password: String): Result +} + +interface IdentityOidcResetHandle : IdentityResetHandle { + val url: String + suspend fun resetOidc(): Result } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt index 68ab4a611e..728fbede55 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt @@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.BackupUploadState import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress import io.element.android.libraries.matrix.api.encryption.EncryptionService +import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.libraries.matrix.api.sync.SyncState import io.element.android.libraries.matrix.impl.sync.RustSyncService @@ -198,4 +199,8 @@ internal class RustEncryptionService( override suspend fun deviceEd25519(): String? { return service.ed25519Key() } + + override suspend fun startIdentityReset(): Result { + return runCatching { service.resetIdentity()?.let(RustIdentityResetHandleFactory::create)?.getOrNull() } + } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt new file mode 100644 index 0000000000..69c7ecdd31 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.encryption + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle +import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle +import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle +import org.matrix.rustcomponents.sdk.AuthData +import org.matrix.rustcomponents.sdk.AuthDataPasswordDetails +import org.matrix.rustcomponents.sdk.CrossSigningResetAuthType + +object RustIdentityResetHandleFactory { + fun create(identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle): Result { + return runCatching { + when (val authType = identityResetHandle.authType()) { + is CrossSigningResetAuthType.Oidc -> RustOidcIdentityResetHandle(identityResetHandle, authType.info.approvalUrl) + // User interactive authentication (user + password) + CrossSigningResetAuthType.Uiaa -> RustPasswordIdentityResetHandle(identityResetHandle) + } + } + } +} + +class RustPasswordIdentityResetHandle( + private val identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle, +) : IdentityPasswordResetHandle { + override suspend fun resetPassword(userId: UserId, password: String): Result { + return runCatching { identityResetHandle.reset(AuthData.Password(AuthDataPasswordDetails(userId.value, password))) } + } +} + +class RustOidcIdentityResetHandle( + private val identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle, + override val url: String, +) : IdentityOidcResetHandle { + override suspend fun resetOidc(): Result { + return runCatching { identityResetHandle.reset(null) } + } +} From ee7a31caceb9c871e38a42dcad596695e6894943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 8 Aug 2024 16:24:13 +0200 Subject: [PATCH 096/186] Extract OIDC to its own module --- appnav/build.gradle.kts | 2 + .../io/element/android/appnav/RootFlowNode.kt | 4 +- .../android/appnav/intent/IntentResolver.kt | 4 +- .../appnav/intent/IntentResolverTest.kt | 6 +- features/login/impl/build.gradle.kts | 2 + .../features/login/impl/LoginFlowNode.kt | 18 ++--- .../ConfirmAccountProviderPresenter.kt | 10 +-- .../ConfirmAccountProviderPresenterTest.kt | 6 +- .../impl/VerifySelfSessionViewTest.kt | 2 + .../test/encryption/FakeEncryptionService.kt | 9 ++- .../encryption/FakeIdentityResetHandle.kt | 38 ++++++++++ libraries/oidc/api/build.gradle.kts | 27 +++++++ .../android/libraries/oidc/api}/OidcAction.kt | 2 +- .../libraries/oidc/api}/OidcActionFlow.kt | 6 +- .../libraries/oidc/api/OidcEntryPoint.kt | 27 +++++++ .../libraries/oidc/api}/OidcIntentResolver.kt | 2 +- libraries/oidc/impl/build.gradle.kts | 71 +++++++++++++++++++ .../impl}/CustomTabAvailabilityChecker.kt | 2 +- .../oidc/impl/DefaultOidcEntryPoint.kt | 49 +++++++++++++ .../oidc/impl}/DefaultOidcIntentResolver.kt | 6 +- .../libraries/oidc/impl}/OidcUrlParser.kt | 4 +- .../oidc/impl}/customtab/CustomTabHandler.kt | 2 +- .../impl}/customtab/DefaultOidcActionFlow.kt | 10 +-- .../oidc/impl}/webview/OidcEvents.kt | 4 +- .../libraries/oidc/impl}/webview/OidcNode.kt | 2 +- .../oidc/impl}/webview/OidcPresenter.kt | 4 +- .../libraries/oidc/impl}/webview/OidcState.kt | 2 +- .../oidc/impl}/webview/OidcStateProvider.kt | 2 +- .../libraries/oidc/impl}/webview/OidcView.kt | 4 +- .../oidc/impl}/webview/OidcWebViewClient.kt | 2 +- .../impl}/webview/WebViewEventListener.kt | 2 +- .../libraries/oidc/impl}/OidcUrlParserTest.kt | 4 +- .../oidc/impl}/webview/OidcPresenterTest.kt | 4 +- .../kotlin/extension/DependencyHandleScope.kt | 1 + 34 files changed, 283 insertions(+), 57 deletions(-) create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt create mode 100644 libraries/oidc/api/build.gradle.kts rename {features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc => libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api}/OidcAction.kt (93%) rename {features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc => libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api}/OidcActionFlow.kt (79%) create mode 100644 libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcEntryPoint.kt rename {features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc => libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api}/OidcIntentResolver.kt (93%) create mode 100644 libraries/oidc/impl/build.gradle.kts rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/CustomTabAvailabilityChecker.kt (95%) create mode 100644 libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcEntryPoint.kt rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/DefaultOidcIntentResolver.kt (85%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/OidcUrlParser.kt (93%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/customtab/CustomTabHandler.kt (97%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/customtab/DefaultOidcActionFlow.kt (82%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/webview/OidcEvents.kt (86%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/webview/OidcNode.kt (96%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/webview/OidcPresenter.kt (96%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/webview/OidcState.kt (93%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/webview/OidcStateProvider.kt (95%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/webview/OidcView.kt (96%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/webview/OidcWebViewClient.kt (95%) rename {features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl}/webview/WebViewEventListener.kt (93%) rename {features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl}/OidcUrlParserTest.kt (94%) rename {features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc => libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl}/webview/OidcPresenterTest.kt (97%) diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index 53680fd44e..887f48e203 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.deeplink) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.oidc.api) implementation(projects.libraries.preferences.api) implementation(projects.libraries.push.api) implementation(projects.libraries.pushproviders.api) @@ -66,6 +67,7 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.oidc.impl) testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushproviders.test) testImplementation(projects.features.networkmonitor.test) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt index d200acb84e..b651f4d77c 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt @@ -42,8 +42,6 @@ import io.element.android.appnav.intent.ResolvedIntent import io.element.android.appnav.root.RootNavStateFlowFactory import io.element.android.appnav.root.RootPresenter import io.element.android.appnav.root.RootView -import io.element.android.features.login.api.oidc.OidcAction -import io.element.android.features.login.api.oidc.OidcActionFlow import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint import io.element.android.features.signedout.api.SignedOutEntryPoint import io.element.android.features.viewfolder.api.ViewFolderEntryPoint @@ -59,6 +57,8 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.sessionstorage.api.LoggedInState +import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.oidc.api.OidcActionFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach diff --git a/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt b/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt index d41fbbfebb..73ad6f6008 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt @@ -17,12 +17,12 @@ package io.element.android.appnav.intent import android.content.Intent -import io.element.android.features.login.api.oidc.OidcAction -import io.element.android.features.login.api.oidc.OidcIntentResolver import io.element.android.libraries.deeplink.DeeplinkData import io.element.android.libraries.deeplink.DeeplinkParser import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkParser +import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.oidc.api.OidcIntentResolver import timber.log.Timber import javax.inject.Inject diff --git a/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt index aa0fe9cbf1..8134c091f6 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt @@ -21,9 +21,6 @@ import android.content.Intent import android.net.Uri import androidx.core.net.toUri import com.google.common.truth.Truth.assertThat -import io.element.android.features.login.api.oidc.OidcAction -import io.element.android.features.login.impl.oidc.DefaultOidcIntentResolver -import io.element.android.features.login.impl.oidc.OidcUrlParser import io.element.android.libraries.deeplink.DeepLinkCreator import io.element.android.libraries.deeplink.DeeplinkData import io.element.android.libraries.deeplink.DeeplinkParser @@ -33,6 +30,9 @@ 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.A_THREAD_ID import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser +import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.oidc.impl.DefaultOidcIntentResolver +import io.element.android.libraries.oidc.impl.OidcUrlParser import io.element.android.tests.testutils.lambda.lambdaError import org.junit.Assert.assertThrows import org.junit.Test diff --git a/features/login/impl/build.gradle.kts b/features/login/impl/build.gradle.kts index 6fcdc2c1de..3fbe55f1f9 100644 --- a/features/login/impl/build.gradle.kts +++ b/features/login/impl/build.gradle.kts @@ -50,6 +50,7 @@ dependencies { implementation(projects.libraries.uiStrings) implementation(projects.libraries.permissions.api) implementation(projects.libraries.qrcode) + implementation(projects.libraries.oidc.api) implementation(libs.androidx.browser) implementation(platform(libs.network.retrofit.bom)) implementation(libs.network.retrofit) @@ -65,6 +66,7 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.oidc.impl) testImplementation(projects.libraries.permissions.test) testImplementation(projects.tests.testutils) testReleaseImplementation(libs.androidx.compose.ui.test.manifest) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt index 0af102a403..13aac03de4 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt @@ -36,12 +36,7 @@ import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.compound.theme.ElementTheme import io.element.android.features.login.api.LoginFlowType -import io.element.android.features.login.api.oidc.OidcAction -import io.element.android.features.login.api.oidc.OidcActionFlow import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource -import io.element.android.features.login.impl.oidc.CustomTabAvailabilityChecker -import io.element.android.features.login.impl.oidc.customtab.CustomTabHandler -import io.element.android.features.login.impl.oidc.webview.OidcNode import io.element.android.features.login.impl.qrcode.QrCodeLoginFlowNode import io.element.android.features.login.impl.screens.changeaccountprovider.ChangeAccountProviderNode import io.element.android.features.login.impl.screens.confirmaccountprovider.ConfirmAccountProviderNode @@ -56,6 +51,9 @@ import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.inputs import io.element.android.libraries.di.AppScope import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.oidc.api.OidcActionFlow +import io.element.android.libraries.oidc.api.OidcEntryPoint import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize @@ -64,11 +62,10 @@ import kotlinx.parcelize.Parcelize class LoginFlowNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val customTabAvailabilityChecker: CustomTabAvailabilityChecker, - private val customTabHandler: CustomTabHandler, private val accountProviderDataSource: AccountProviderDataSource, private val defaultLoginUserStory: DefaultLoginUserStory, private val oidcActionFlow: OidcActionFlow, + private val oidcEntryPoint: OidcEntryPoint, ) : BaseFlowNode( backstack = BackStack( initialElement = NavTarget.Root, @@ -146,11 +143,11 @@ class LoginFlowNode @AssistedInject constructor( ) val callback = object : ConfirmAccountProviderNode.Callback { override fun onOidcDetails(oidcDetails: OidcDetails) { - if (customTabAvailabilityChecker.supportCustomTab()) { + if (oidcEntryPoint.canUseCustomTab()) { // In this case open a Chrome Custom tab activity?.let { customChromeTabStarted = true - customTabHandler.open(it, darkTheme, oidcDetails.url) + oidcEntryPoint.openUrlInCustomTab(it, darkTheme, oidcDetails.url) } } else { // Fallback to WebView mode @@ -201,8 +198,7 @@ class LoginFlowNode @AssistedInject constructor( createNode(buildContext, plugins = listOf(callback)) } is NavTarget.OidcView -> { - val input = OidcNode.Inputs(navTarget.oidcDetails) - createNode(buildContext, plugins = listOf(input)) + oidcEntryPoint.createFallbackWebViewNode(this, buildContext, navTarget.oidcDetails.url) } is NavTarget.WaitList -> { val inputs = WaitListNode.Inputs( diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt index 27aec75739..fdf7994d7e 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt @@ -27,15 +27,15 @@ import androidx.compose.runtime.rememberCoroutineScope import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import io.element.android.features.login.api.oidc.OidcAction import io.element.android.features.login.impl.DefaultLoginUserStory import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.error.ChangeServerError -import io.element.android.features.login.impl.oidc.customtab.DefaultOidcActionFlow import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService +import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.oidc.api.OidcActionFlow import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -43,7 +43,7 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor( @Assisted private val params: Params, private val accountProviderDataSource: AccountProviderDataSource, private val authenticationService: MatrixAuthenticationService, - private val defaultOidcActionFlow: DefaultOidcActionFlow, + private val oidcActionFlow: OidcActionFlow, private val defaultLoginUserStory: DefaultLoginUserStory, ) : Presenter { data class Params( @@ -65,7 +65,7 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor( } LaunchedEffect(Unit) { - defaultOidcActionFlow.collect { oidcAction -> + oidcActionFlow.collect { oidcAction -> if (oidcAction != null) { onOidcAction(oidcAction, loginFlowAction) } @@ -133,6 +133,6 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor( } } } - defaultOidcActionFlow.reset() + oidcActionFlow.reset() } } diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt index 5a02797bdb..3875a4b245 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt @@ -20,10 +20,8 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.login.api.oidc.OidcAction import io.element.android.features.login.impl.DefaultLoginUserStory import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource -import io.element.android.features.login.impl.oidc.customtab.DefaultOidcActionFlow import io.element.android.features.login.impl.util.defaultAccountProvider import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService @@ -31,6 +29,8 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER import io.element.android.libraries.matrix.test.A_HOMESERVER_OIDC import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService +import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.oidc.impl.customtab.DefaultOidcActionFlow import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.waitForPredicate import kotlinx.coroutines.test.runTest @@ -274,7 +274,7 @@ class ConfirmAccountProviderPresenterTest { params = params, accountProviderDataSource = accountProviderDataSource, authenticationService = matrixAuthenticationService, - defaultOidcActionFlow = defaultOidcActionFlow, + oidcActionFlow = defaultOidcActionFlow, defaultLoginUserStory = defaultLoginUserStory, ) } diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionViewTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionViewTest.kt index f19f3e1f29..7e5bf928e2 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionViewTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionViewTest.kt @@ -217,12 +217,14 @@ class VerifySelfSessionViewTest { state: VerifySelfSessionState, onEnterRecoveryKey: () -> Unit = EnsureNeverCalled(), onFinished: () -> Unit = EnsureNeverCalled(), + onResetKey: () -> Unit = EnsureNeverCalled(), ) { setContent { VerifySelfSessionView( state = state, onEnterRecoveryKey = onEnterRecoveryKey, onFinish = onFinished, + onResetKey = onResetKey, ) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt index b864c69b0b..fa301e402e 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt @@ -20,13 +20,16 @@ import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.BackupUploadState import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress import io.element.android.libraries.matrix.api.encryption.EncryptionService +import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.tests.testutils.simulateLongTask import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf -class FakeEncryptionService : EncryptionService { +class FakeEncryptionService( + var startIdentityResetLambda: () -> Result = { error("Not implemented") }, +) : EncryptionService { private var disableRecoveryFailure: Exception? = null override val backupStateStateFlow: MutableStateFlow = MutableStateFlow(BackupState.UNKNOWN) override val recoveryStateStateFlow: MutableStateFlow = MutableStateFlow(RecoveryState.UNKNOWN) @@ -118,6 +121,10 @@ class FakeEncryptionService : EncryptionService { enableRecoveryProgressStateFlow.emit(state) } + override suspend fun startIdentityReset(): Result { + return startIdentityResetLambda() + } + companion object { const val FAKE_RECOVERY_KEY = "fake" } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt new file mode 100644 index 0000000000..bf0aa312be --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.test.encryption + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle +import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle + +class FakeIdentityOidcResetHandle( + override val url: String = "", + var resetOidcLambda: () -> Result = { error("Not implemented") } +) : IdentityOidcResetHandle { + override suspend fun resetOidc(): Result { + return resetOidcLambda() + } +} + +class FakeIdentityPasswordResetHandle( + var resetPasswordLambda: (UserId, String) -> Result = { _, _ -> error("Not implemented") } +) : IdentityPasswordResetHandle { + override suspend fun resetPassword(userId: UserId, password: String): Result { + return resetPasswordLambda(userId, password) + } +} diff --git a/libraries/oidc/api/build.gradle.kts b/libraries/oidc/api/build.gradle.kts new file mode 100644 index 0000000000..874c3ddbd4 --- /dev/null +++ b/libraries/oidc/api/build.gradle.kts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +plugins { + id("io.element.android-library") + id("kotlin-parcelize") +} + +android { + namespace = "io.element.android.libraries.oidc.api" +} + +dependencies { + implementation(projects.libraries.architecture) +} diff --git a/features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcAction.kt b/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcAction.kt similarity index 93% rename from features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcAction.kt rename to libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcAction.kt index 6d87872879..cc17159960 100644 --- a/features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcAction.kt +++ b/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcAction.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.api.oidc +package io.element.android.libraries.oidc.api sealed interface OidcAction { data object GoBack : OidcAction diff --git a/features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcActionFlow.kt b/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcActionFlow.kt similarity index 79% rename from features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcActionFlow.kt rename to libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcActionFlow.kt index 004e7c8a51..1fd67cfaf5 100644 --- a/features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcActionFlow.kt +++ b/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcActionFlow.kt @@ -14,8 +14,12 @@ * limitations under the License. */ -package io.element.android.features.login.api.oidc +package io.element.android.libraries.oidc.api + +import kotlinx.coroutines.flow.FlowCollector interface OidcActionFlow { fun post(oidcAction: OidcAction) + suspend fun collect(collector: FlowCollector) + fun reset() } diff --git a/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcEntryPoint.kt b/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcEntryPoint.kt new file mode 100644 index 0000000000..c00bf263af --- /dev/null +++ b/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcEntryPoint.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.oidc.api + +import android.app.Activity +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node + +interface OidcEntryPoint { + fun canUseCustomTab(): Boolean + fun openUrlInCustomTab(activity: Activity, darkTheme: Boolean, url: String) + fun createFallbackWebViewNode(parentNode: Node, buildContext: BuildContext, url: String): Node +} diff --git a/features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcIntentResolver.kt b/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcIntentResolver.kt similarity index 93% rename from features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcIntentResolver.kt rename to libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcIntentResolver.kt index a6ecf26fca..77597fd432 100644 --- a/features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcIntentResolver.kt +++ b/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcIntentResolver.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.api.oidc +package io.element.android.libraries.oidc.api import android.content.Intent diff --git a/libraries/oidc/impl/build.gradle.kts b/libraries/oidc/impl/build.gradle.kts new file mode 100644 index 0000000000..be4181e169 --- /dev/null +++ b/libraries/oidc/impl/build.gradle.kts @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-compose-library") + alias(libs.plugins.anvil) + id("kotlin-parcelize") + alias(libs.plugins.kotlin.serialization) +} + +android { + namespace = "io.element.android.libraries.oidc.impl" + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } +} + +anvil { + generateDaggerFactories.set(true) +} + +dependencies { + implementation(projects.anvilannotations) + implementation(projects.appconfig) + anvil(projects.anvilcodegen) + implementation(projects.libraries.core) + implementation(projects.libraries.androidutils) + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) + implementation(projects.libraries.matrix.api) + implementation(projects.libraries.network) + implementation(projects.libraries.designsystem) + implementation(projects.libraries.testtags) + implementation(projects.libraries.uiStrings) + implementation(projects.libraries.permissions.api) + implementation(projects.libraries.qrcode) + implementation(libs.androidx.browser) + implementation(platform(libs.network.retrofit.bom)) + implementation(libs.network.retrofit) + implementation(libs.serialization.json) + api(projects.libraries.oidc.api) + + testImplementation(libs.test.junit) + testImplementation(libs.androidx.compose.ui.test.junit) + testImplementation(libs.androidx.test.ext.junit) + testImplementation(libs.coroutines.test) + testImplementation(libs.molecule.runtime) + testImplementation(libs.test.robolectric) + testImplementation(libs.test.truth) + testImplementation(libs.test.turbine) + testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.permissions.test) + testImplementation(projects.tests.testutils) + testReleaseImplementation(libs.androidx.compose.ui.test.manifest) +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/CustomTabAvailabilityChecker.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/CustomTabAvailabilityChecker.kt similarity index 95% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/CustomTabAvailabilityChecker.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/CustomTabAvailabilityChecker.kt index 424e9f13bc..6258e67b0e 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/CustomTabAvailabilityChecker.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/CustomTabAvailabilityChecker.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc +package io.element.android.libraries.oidc.impl import android.content.Context import androidx.browser.customtabs.CustomTabsClient diff --git a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcEntryPoint.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcEntryPoint.kt new file mode 100644 index 0000000000..1a8ce960c5 --- /dev/null +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcEntryPoint.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.oidc.impl + +import android.app.Activity +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.oidc.impl.webview.OidcNode +import io.element.android.libraries.oidc.api.OidcEntryPoint +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class DefaultOidcEntryPoint @Inject constructor( + private val customTabAvailabilityChecker: CustomTabAvailabilityChecker, +) : OidcEntryPoint { + override fun canUseCustomTab(): Boolean { + return customTabAvailabilityChecker.supportCustomTab() + } + + override fun openUrlInCustomTab(activity: Activity, darkTheme: Boolean, url: String) { + assert(canUseCustomTab()) { "Custom tab is not supported in this device." } + activity.openUrlInChromeCustomTab(null, darkTheme, url) + } + + override fun createFallbackWebViewNode(parentNode: Node, buildContext: BuildContext, url: String): Node { + assert(!canUseCustomTab()) { "Custom tab should be used instead of the fallback node." } + val inputs = OidcNode.Inputs(OidcDetails(url)) + return parentNode.createNode(buildContext, listOf(inputs)) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/DefaultOidcIntentResolver.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolver.kt similarity index 85% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/DefaultOidcIntentResolver.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolver.kt index 8b6844e0f3..9777cee22f 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/DefaultOidcIntentResolver.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolver.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc +package io.element.android.libraries.oidc.impl import android.content.Intent import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.features.login.api.oidc.OidcAction -import io.element.android.features.login.api.oidc.OidcIntentResolver import io.element.android.libraries.di.AppScope +import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.oidc.api.OidcIntentResolver import javax.inject.Inject @ContributesBinding(AppScope::class) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/OidcUrlParser.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParser.kt similarity index 93% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/OidcUrlParser.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParser.kt index 8c8c895acd..ae502d0a8c 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/OidcUrlParser.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParser.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc +package io.element.android.libraries.oidc.impl -import io.element.android.features.login.api.oidc.OidcAction import io.element.android.libraries.matrix.api.auth.OidcConfig +import io.element.android.libraries.oidc.api.OidcAction import javax.inject.Inject /** diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/CustomTabHandler.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/customtab/CustomTabHandler.kt similarity index 97% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/CustomTabHandler.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/customtab/CustomTabHandler.kt index b83c0eb1ac..21c673145e 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/CustomTabHandler.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/customtab/CustomTabHandler.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc.customtab +package io.element.android.libraries.oidc.impl.customtab import android.app.Activity import android.content.ComponentName diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/DefaultOidcActionFlow.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/customtab/DefaultOidcActionFlow.kt similarity index 82% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/DefaultOidcActionFlow.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/customtab/DefaultOidcActionFlow.kt index 17dfa8418f..0c0737b43e 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/DefaultOidcActionFlow.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/customtab/DefaultOidcActionFlow.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc.customtab +package io.element.android.libraries.oidc.impl.customtab import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.features.login.api.oidc.OidcAction -import io.element.android.features.login.api.oidc.OidcActionFlow import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.SingleIn +import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.oidc.api.OidcActionFlow import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.MutableStateFlow import javax.inject.Inject @@ -34,11 +34,11 @@ class DefaultOidcActionFlow @Inject constructor() : OidcActionFlow { mutableStateFlow.value = oidcAction } - suspend fun collect(collector: FlowCollector) { + override suspend fun collect(collector: FlowCollector) { mutableStateFlow.collect(collector) } - fun reset() { + override fun reset() { mutableStateFlow.value = null } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcEvents.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcEvents.kt similarity index 86% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcEvents.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcEvents.kt index 9d2f945e25..602d50628a 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcEvents.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcEvents.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc.webview +package io.element.android.libraries.oidc.impl.webview -import io.element.android.features.login.api.oidc.OidcAction +import io.element.android.libraries.oidc.api.OidcAction sealed interface OidcEvents { data object Cancel : OidcEvents diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcNode.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcNode.kt similarity index 96% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcNode.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcNode.kt index 5cd7cf0c3b..d31bdcd032 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcNode.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcNode.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc.webview +package io.element.android.libraries.oidc.impl.webview import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenter.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenter.kt similarity index 96% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenter.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenter.kt index 3f10ba256a..853a9b584c 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenter.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenter.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc.webview +package io.element.android.libraries.oidc.impl.webview import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -25,7 +25,7 @@ import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import io.element.android.features.login.api.oidc.OidcAction +import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcState.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcState.kt similarity index 93% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcState.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcState.kt index dc4f26d51e..8b1b01b03d 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcState.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc.webview +package io.element.android.libraries.oidc.impl.webview import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.auth.OidcDetails diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcStateProvider.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcStateProvider.kt similarity index 95% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcStateProvider.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcStateProvider.kt index 5d44657462..7127c9160e 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcStateProvider.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcStateProvider.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc.webview +package io.element.android.libraries.oidc.impl.webview import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.architecture.AsyncAction diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcView.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt similarity index 96% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcView.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt index c07078cdff..e8ddcd03c3 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcView.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc.webview +package io.element.android.libraries.oidc.impl.webview import android.webkit.WebView import androidx.activity.compose.BackHandler @@ -28,11 +28,11 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.viewinterop.AndroidView -import io.element.android.features.login.impl.oidc.OidcUrlParser import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.designsystem.components.async.AsyncActionView import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.oidc.impl.OidcUrlParser @Composable fun OidcView( diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcWebViewClient.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcWebViewClient.kt similarity index 95% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcWebViewClient.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcWebViewClient.kt index a9cd576e6d..d20eabf00e 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcWebViewClient.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcWebViewClient.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc.webview +package io.element.android.libraries.oidc.impl.webview import android.webkit.WebResourceRequest import android.webkit.WebView diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/WebViewEventListener.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/WebViewEventListener.kt similarity index 93% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/WebViewEventListener.kt rename to libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/WebViewEventListener.kt index 446754aced..8f587966bf 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/WebViewEventListener.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/WebViewEventListener.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc.webview +package io.element.android.libraries.oidc.impl.webview fun interface WebViewEventListener { /** diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/OidcUrlParserTest.kt b/libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParserTest.kt similarity index 94% rename from features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/OidcUrlParserTest.kt rename to libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParserTest.kt index 6f63673b23..895e416faa 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/OidcUrlParserTest.kt +++ b/libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParserTest.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package io.element.android.features.login.impl.oidc +package io.element.android.libraries.oidc.impl import com.google.common.truth.Truth.assertThat -import io.element.android.features.login.api.oidc.OidcAction import io.element.android.libraries.matrix.api.auth.OidcConfig +import io.element.android.libraries.oidc.api.OidcAction import org.junit.Assert import org.junit.Test diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt b/libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenterTest.kt similarity index 97% rename from features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt rename to libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenterTest.kt index 38d0506dd8..994334d2e9 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt +++ b/libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenterTest.kt @@ -16,17 +16,17 @@ @file:OptIn(ExperimentalCoroutinesApi::class) -package io.element.android.features.login.impl.oidc.webview +package io.element.android.libraries.oidc.impl.webview import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.login.api.oidc.OidcAction import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.auth.A_OIDC_DATA import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService +import io.element.android.libraries.oidc.api.OidcAction import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index 9fd82af4ae..bd83d527ca 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -116,6 +116,7 @@ fun DependencyHandlerScope.allLibrariesImpl() { implementation(project(":libraries:mediaviewer:impl")) implementation(project(":libraries:troubleshoot:impl")) implementation(project(":libraries:fullscreenintent:impl")) + implementation(project(":libraries:oidc:impl")) } fun DependencyHandlerScope.allServicesImpl() { From abb995978940a9ae168f46cbb910a6361dcda1ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 8 Aug 2024 16:37:11 +0200 Subject: [PATCH 097/186] Use extracted OIDC flow to display the reset identity screen --- features/securebackup/impl/build.gradle.kts | 1 + .../impl/reset/ResetIdentityFlowNode.kt | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/features/securebackup/impl/build.gradle.kts b/features/securebackup/impl/build.gradle.kts index 41f3ba8942..a2a2e04a5d 100644 --- a/features/securebackup/impl/build.gradle.kts +++ b/features/securebackup/impl/build.gradle.kts @@ -45,6 +45,7 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) + implementation(projects.libraries.oidc.api) implementation(projects.libraries.uiStrings) implementation(projects.libraries.testtags) api(libs.statemachine) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt index a7c0011625..11dfb71c22 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt @@ -41,6 +41,7 @@ import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle +import io.element.android.libraries.oidc.api.OidcEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first @@ -53,6 +54,7 @@ class ResetIdentityFlowNode @AssistedInject constructor( @Assisted plugins: List, private val resetIdentityFlowManager: ResetIdentityFlowManager, private val coroutineScope: CoroutineScope, + private val oidcEntryPoint: OidcEntryPoint, ) : BaseFlowNode( backstack = BackStack(initialElement = NavTarget.Root, savedStateMap = buildContext.savedStateMap), buildContext = buildContext, @@ -69,8 +71,8 @@ class ResetIdentityFlowNode @AssistedInject constructor( @Parcelize data object ResetPassword : NavTarget -// @Parcelize -// data class ResetOidc(val url: String) : NavTarget + @Parcelize + data class ResetOidc(val url: String) : NavTarget } private lateinit var activity: Activity @@ -100,6 +102,9 @@ class ResetIdentityFlowNode @AssistedInject constructor( listOf(ResetKeyPasswordNode.Inputs(resetIdentityFlowManager.currentSessionId(), handle)) ) } + is NavTarget.ResetOidc -> { + oidcEntryPoint.createFallbackWebViewNode(this, buildContext, navTarget.url) + } } } @@ -111,7 +116,11 @@ class ResetIdentityFlowNode @AssistedInject constructor( when (handle) { is IdentityOidcResetHandle -> { - activity.openUrlInChromeCustomTab(null, false, handle.url) + if (oidcEntryPoint.canUseCustomTab()) { + activity.openUrlInChromeCustomTab(null, false, handle.url) + } else { + backstack.push(NavTarget.ResetOidc(handle.url)) + } handle.resetOidc() } is IdentityPasswordResetHandle -> backstack.push(NavTarget.ResetPassword) From 175bada0df0e8b80c3ffe9c08ec3df5937fb59e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 9 Aug 2024 09:34:04 +0200 Subject: [PATCH 098/186] Improve existing APIs --- .../impl/reset/ResetIdentityFlowManager.kt | 10 ++--- .../impl/reset/ResetIdentityFlowNode.kt | 38 ++++++++++++++++++- .../androidutils/browser/ChromeCustomTab.kt | 7 ++++ .../api/encryption/EncryptionService.kt | 38 ++++++++++++++++++- .../encryption/RustIdentityResetHandle.kt | 13 +++++++ .../encryption/FakeIdentityResetHandle.kt | 14 ++++++- .../libraries/oidc/impl/webview/OidcView.kt | 34 +++++++++++++++-- 7 files changed, 140 insertions(+), 14 deletions(-) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt index 76674cd87d..fa4f693cd3 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt @@ -17,8 +17,6 @@ package io.element.android.features.securebackup.impl.reset import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.di.SessionScope -import io.element.android.libraries.di.SingleIn import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.SessionId @@ -28,11 +26,8 @@ import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatu import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import javax.inject.Inject @@ -76,4 +71,9 @@ class ResetIdentityFlowManager @Inject constructor( resetHandleFlow } } + + suspend fun cancel() { + currentHandleFlow.value.dataOrNull()?.cancel() + resetHandleFlow.value = AsyncData.Uninitialized + } } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt index 11dfb71c22..e144a52432 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt @@ -19,8 +19,12 @@ package io.element.android.features.securebackup.impl.reset import android.app.Activity import android.os.Parcelable import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin @@ -37,12 +41,14 @@ import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.BackstackView import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle import io.element.android.libraries.oidc.api.OidcEntryPoint import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch @@ -76,6 +82,7 @@ class ResetIdentityFlowNode @AssistedInject constructor( } private lateinit var activity: Activity + private var resetJob: Job? = null override fun onBuilt() { super.onBuilt() @@ -83,6 +90,19 @@ class ResetIdentityFlowNode @AssistedInject constructor( resetIdentityFlowManager.whenResetIsDone { plugins().forEach { it.onDone() } } + + lifecycle.addObserver(object : DefaultLifecycleObserver { + override fun onStart(owner: LifecycleOwner) { + // If the custom tab was opened, we need to cancel the reset job + // when we come back to the node if it the reset wasn't successful + cancelResetJob() + } + + override fun onDestroy(owner: LifecycleOwner) { + // Make sure we cancel the reset job when the node is destroyed, just in case + cancelResetJob() + } + }) } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { @@ -121,15 +141,29 @@ class ResetIdentityFlowNode @AssistedInject constructor( } else { backstack.push(NavTarget.ResetOidc(handle.url)) } - handle.resetOidc() + resetJob = launch { handle.resetOidc() } } is IdentityPasswordResetHandle -> backstack.push(NavTarget.ResetPassword) } } + private fun cancelResetJob() { + resetJob?.cancel() + resetJob = null + coroutineScope.launch { resetIdentityFlowManager.cancel() } + } + @Composable override fun View(modifier: Modifier) { - (LocalContext.current as? Activity)?.let { activity = it } + // Workaround to get the current activity + if (!this::activity.isInitialized) { + activity = LocalContext.current as Activity + } + + val startResetState by resetIdentityFlowManager.currentHandleFlow.collectAsState() + if (startResetState.isLoading()) { + ProgressDialog() + } BackstackView(modifier) } 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 ec0d9662c7..425133b797 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 @@ -47,12 +47,19 @@ fun Activity.openUrlInChromeCustomTab( true -> CustomTabsIntent.COLOR_SCHEME_DARK } ) + .setShareIdentityEnabled(false) // Note: setting close button icon does not work // .setCloseButtonIcon(BitmapFactory.decodeResource(context.resources, R.drawable.ic_back_24dp)) // .setStartAnimations(context, R.anim.enter_fade_in, R.anim.exit_fade_out) // .setExitAnimations(context, R.anim.enter_fade_in, R.anim.exit_fade_out) .apply { session?.let { setSession(it) } } .build() + .apply { + // Disable download button + intent.putExtra("org.chromium.chrome.browser.customtabs.EXTRA_DISABLE_DOWNLOAD_BUTTON", true) + // Disable bookmark button + intent.putExtra("org.chromium.chrome.browser.customtabs.EXTRA_DISABLE_START_BUTTON", true) + } .launchUrl(this, Uri.parse(url)) } catch (activityNotFoundException: ActivityNotFoundException) { // TODO context.toast(R.string.error_no_external_application_found) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt index fdaebc9c97..420940aefe 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt @@ -64,16 +64,52 @@ interface EncryptionService { */ suspend fun deviceEd25519(): String? + /** + * Starts the identity reset process. This will return a handle that can be used to reset the identity. + */ suspend fun startIdentityReset(): Result } -interface IdentityResetHandle +/** + * A handle to reset the user's identity. + */ +interface IdentityResetHandle { + /** + * Cancel the reset process and drops the existing handle in the SDK. + */ + suspend fun cancel() +} +/** + * A handle to reset the user's identity with a password login type. + */ interface IdentityPasswordResetHandle : IdentityResetHandle { + /** + * Reset the password of the user. + * + * This method will block the coroutine it's running on and keep polling indefinitely until either the coroutine is cancelled, the [cancel] method is + * called, or the identity is reset. + * + * @param userId the user id of the user to reset the password for. + * @param password the current password, which will be validated before the process takes place. + */ suspend fun resetPassword(userId: UserId, password: String): Result } +/** + * A handle to reset the user's identity with an OIDC login type. + */ interface IdentityOidcResetHandle : IdentityResetHandle { + /** + * The URL to open in a webview/custom tab to reset the identity. + */ val url: String + + /** + * Reset the identity using the OIDC flow. + * + * This method will block the coroutine it's running on and keep polling indefinitely until either the coroutine is cancelled, the [cancel] method is + * called, or the identity is reset. + */ suspend fun resetOidc(): Result } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt index 69c7ecdd31..0d51d7c4c2 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt @@ -42,6 +42,10 @@ class RustPasswordIdentityResetHandle( override suspend fun resetPassword(userId: UserId, password: String): Result { return runCatching { identityResetHandle.reset(AuthData.Password(AuthDataPasswordDetails(userId.value, password))) } } + + override suspend fun cancel() { + identityResetHandle.cancelAndDestroy() + } } class RustOidcIdentityResetHandle( @@ -51,4 +55,13 @@ class RustOidcIdentityResetHandle( override suspend fun resetOidc(): Result { return runCatching { identityResetHandle.reset(null) } } + + override suspend fun cancel() { + identityResetHandle.cancelAndDestroy() + } +} + +private suspend fun org.matrix.rustcomponents.sdk.IdentityResetHandle.cancelAndDestroy() { + cancel() + destroy() } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt index bf0aa312be..6b3eabd102 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt @@ -22,17 +22,27 @@ import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetH class FakeIdentityOidcResetHandle( override val url: String = "", - var resetOidcLambda: () -> Result = { error("Not implemented") } + var resetOidcLambda: () -> Result = { error("Not implemented") }, + var cancelLambda: () -> Unit = { error("Not implemented") }, ) : IdentityOidcResetHandle { override suspend fun resetOidc(): Result { return resetOidcLambda() } + + override suspend fun cancel() { + cancelLambda() + } } class FakeIdentityPasswordResetHandle( - var resetPasswordLambda: (UserId, String) -> Result = { _, _ -> error("Not implemented") } + var resetPasswordLambda: (UserId, String) -> Result = { _, _ -> error("Not implemented") }, + var cancelLambda: () -> Unit = { error("Not implemented") }, ) : IdentityPasswordResetHandle { override suspend fun resetPassword(userId: UserId, password: String): Result { return resetPasswordLambda(userId, password) } + + override suspend fun cancel() { + cancelLambda() + } } diff --git a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt index e8ddcd03c3..56a04cb0ea 100644 --- a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt @@ -16,10 +16,11 @@ package io.element.android.libraries.oidc.impl.webview +import android.annotation.SuppressLint import android.webkit.WebView import androidx.activity.compose.BackHandler -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -30,10 +31,14 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.viewinterop.AndroidView import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.designsystem.components.async.AsyncActionView +import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.oidc.impl.OidcUrlParser +@OptIn(ExperimentalMaterial3Api::class) @Composable fun OidcView( state: OidcState, @@ -55,7 +60,7 @@ fun OidcView( OidcWebViewClient(::shouldOverrideUrl) } - BackHandler { + fun onBack() { if (webView?.canGoBack().orFalse()) { webView?.goBack() } else { @@ -64,11 +69,32 @@ fun OidcView( } } - Box(modifier = modifier.statusBarsPadding()) { + BackHandler { onBack() } + + Scaffold( + modifier = modifier, + topBar = { + TopAppBar( + title = {}, + navigationIcon = { + BackButton(onClick = ::onBack) + }, + ) + } + ) { contentPadding -> AndroidView( + modifier = Modifier.padding(contentPadding), factory = { context -> WebView(context).apply { webViewClient = oidcWebViewClient + settings.apply { + @SuppressLint("SetJavaScriptEnabled") + javaScriptEnabled = true + allowContentAccess = true + allowFileAccess = true + databaseEnabled = true + domStorageEnabled = true + } loadUrl(state.oidcDetails.url) }.also { webView = it From 7fd0ad09dc7069ab6e4280229d752e10dff6164b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 12 Aug 2024 12:22:36 +0200 Subject: [PATCH 099/186] Improve APIs, add tests --- .../impl/reset/ResetIdentityFlowManager.kt | 5 - .../impl/reset/ResetIdentityFlowNode.kt | 12 +- ...Event.kt => ResetIdentityPasswordEvent.kt} | 6 +- ...rdNode.kt => ResetIdentityPasswordNode.kt} | 12 +- ...r.kt => ResetIdentityPasswordPresenter.kt} | 22 ++-- ...State.kt => ResetIdentityPasswordState.kt} | 4 +- ...rdView.kt => ResetIdentityPasswordView.kt} | 14 +-- ...RootEvent.kt => ResetIdentityRootEvent.kt} | 6 +- ...eyRootNode.kt => ResetIdentityRootNode.kt} | 6 +- ...enter.kt => ResetIdentityRootPresenter.kt} | 12 +- ...RootState.kt => ResetIdentityRootState.kt} | 4 +- ...r.kt => ResetIdentityRootStateProvider.kt} | 8 +- ...eyRootView.kt => ResetIdentityRootView.kt} | 14 +-- .../reset/ResetIdentityFlowManagerTests.kt | 119 ++++++++++++++++++ .../ResetIdentityPasswordPresenterTest.kt | 96 ++++++++++++++ .../password/ResetIdentityPasswordViewTest.kt | 97 ++++++++++++++ .../root/ResetIdentityRootPresenterTests.kt | 65 ++++++++++ .../reset/root/ResetIdentityRootViewTests.kt | 107 ++++++++++++++++ .../api/encryption/EncryptionService.kt | 4 +- .../impl/encryption/RustEncryptionService.kt | 8 +- .../encryption/RustIdentityResetHandle.kt | 10 +- .../encryption/FakeIdentityResetHandle.kt | 7 +- 22 files changed, 562 insertions(+), 76 deletions(-) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/{ResetKeyPasswordEvent.kt => ResetIdentityPasswordEvent.kt} (79%) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/{ResetKeyPasswordNode.kt => ResetIdentityPasswordNode.kt} (81%) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/{ResetKeyPasswordPresenter.kt => ResetIdentityPasswordPresenter.kt} (68%) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/{ResetKeyPasswordState.kt => ResetIdentityPasswordState.kt} (89%) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/{ResetKeyPasswordView.kt => ResetIdentityPasswordView.kt} (92%) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/{ResetKeyRootEvent.kt => ResetIdentityRootEvent.kt} (82%) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/{ResetKeyRootNode.kt => ResetIdentityRootNode.kt} (91%) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/{ResetKeyRootPresenter.kt => ResetIdentityRootPresenter.kt} (78%) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/{ResetKeyRootState.kt => ResetIdentityRootState.kt} (89%) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/{ResetKeyRootStateProvider.kt => ResetIdentityRootStateProvider.kt} (81%) rename features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/{ResetKeyRootView.kt => ResetIdentityRootView.kt} (92%) create mode 100644 features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTests.kt create mode 100644 features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordPresenterTest.kt create mode 100644 features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt create mode 100644 features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenterTests.kt create mode 100644 features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTests.kt diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt index fa4f693cd3..3425ca90be 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt @@ -19,7 +19,6 @@ package io.element.android.features.securebackup.impl.reset import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.matrix.api.MatrixClient -import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus @@ -46,10 +45,6 @@ class ResetIdentityFlowManager @Inject constructor( } } - fun currentSessionId(): SessionId { - return matrixClient.sessionId - } - fun getResetHandle(): StateFlow> { return if (resetHandleFlow.value.isLoading() || resetHandleFlow.value.isSuccess()) { resetHandleFlow diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt index e144a52432..0f0278cb66 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt @@ -34,8 +34,8 @@ import com.bumble.appyx.navmodel.backstack.operation.push import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode -import io.element.android.features.securebackup.impl.reset.password.ResetKeyPasswordNode -import io.element.android.features.securebackup.impl.reset.root.ResetKeyRootNode +import io.element.android.features.securebackup.impl.reset.password.ResetIdentityPasswordNode +import io.element.android.features.securebackup.impl.reset.root.ResetIdentityRootNode import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.BackstackView @@ -108,18 +108,18 @@ class ResetIdentityFlowNode @AssistedInject constructor( override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { is NavTarget.Root -> { - val callback = object : ResetKeyRootNode.Callback { + val callback = object : ResetIdentityRootNode.Callback { override fun onContinue() { coroutineScope.startReset() } } - createNode(buildContext, listOf(callback)) + createNode(buildContext, listOf(callback)) } is NavTarget.ResetPassword -> { val handle = resetIdentityFlowManager.currentHandleFlow.value.dataOrNull() as? IdentityPasswordResetHandle ?: error("No password handle found") - createNode( + createNode( buildContext, - listOf(ResetKeyPasswordNode.Inputs(resetIdentityFlowManager.currentSessionId(), handle)) + listOf(ResetIdentityPasswordNode.Inputs(handle)) ) } is NavTarget.ResetOidc -> { diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordEvent.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordEvent.kt similarity index 79% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordEvent.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordEvent.kt index 5fce7cdf85..b76dff920f 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordEvent.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordEvent.kt @@ -16,7 +16,7 @@ package io.element.android.features.securebackup.impl.reset.password -sealed interface ResetKeyPasswordEvent { - data class Reset(val password: String) : ResetKeyPasswordEvent - data object DismissError : ResetKeyPasswordEvent +sealed interface ResetIdentityPasswordEvent { + data class Reset(val password: String) : ResetIdentityPasswordEvent + data object DismissError : ResetIdentityPasswordEvent } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt similarity index 81% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordNode.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt index c430bbec28..7397361b03 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt @@ -21,33 +21,33 @@ import androidx.compose.ui.Modifier import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin -import com.bumble.appyx.core.plugin.plugins import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.SessionScope -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle @ContributesNode(SessionScope::class) -class ResetKeyPasswordNode @AssistedInject constructor( +class ResetIdentityPasswordNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, + private val coroutineDispatchers: CoroutineDispatchers, ) : Node(buildContext, plugins = plugins) { - data class Inputs(val userId: UserId, val handle: IdentityPasswordResetHandle) : NodeInputs + data class Inputs(val handle: IdentityPasswordResetHandle) : NodeInputs private val presenter by lazy { val inputs = inputs() - ResetKeyPasswordPresenter(inputs.userId, inputs.handle) + ResetIdentityPasswordPresenter(inputs.handle, dispatchers = coroutineDispatchers) } @Composable override fun View(modifier: Modifier) { val state = presenter.present() - ResetKeyPasswordView( + ResetIdentityPasswordView( state = state, onBack = ::navigateUp ) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordPresenter.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordPresenter.kt similarity index 68% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordPresenter.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordPresenter.kt index 19fa002108..baa8ab2844 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordPresenter.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordPresenter.kt @@ -24,37 +24,37 @@ import androidx.compose.runtime.rememberCoroutineScope import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState -import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch -class ResetKeyPasswordPresenter( - private val userId: UserId, +class ResetIdentityPasswordPresenter( private val identityPasswordResetHandle: IdentityPasswordResetHandle, -) : Presenter { + private val dispatchers: CoroutineDispatchers, +) : Presenter { @Composable - override fun present(): ResetKeyPasswordState { + override fun present(): ResetIdentityPasswordState { val coroutineScope = rememberCoroutineScope() val resetAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } - fun handleEvent(event: ResetKeyPasswordEvent) { + fun handleEvent(event: ResetIdentityPasswordEvent) { when (event) { - is ResetKeyPasswordEvent.Reset -> coroutineScope.reset(userId, event.password, resetAction) - ResetKeyPasswordEvent.DismissError -> resetAction.value = AsyncAction.Uninitialized + is ResetIdentityPasswordEvent.Reset -> coroutineScope.reset(event.password, resetAction) + ResetIdentityPasswordEvent.DismissError -> resetAction.value = AsyncAction.Uninitialized } } - return ResetKeyPasswordState( + return ResetIdentityPasswordState( resetAction = resetAction.value, eventSink = ::handleEvent ) } - private fun CoroutineScope.reset(userId: UserId, password: String, action: MutableState>) = launch { + private fun CoroutineScope.reset(password: String, action: MutableState>) = launch(dispatchers.io) { suspend { - identityPasswordResetHandle.resetPassword(userId, password).getOrThrow() + identityPasswordResetHandle.resetPassword(password).getOrThrow() }.runCatchingUpdatingState(action) } } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordState.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordState.kt similarity index 89% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordState.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordState.kt index 3de58ec032..47662b623e 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordState.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordState.kt @@ -18,7 +18,7 @@ package io.element.android.features.securebackup.impl.reset.password import io.element.android.libraries.architecture.AsyncAction -data class ResetKeyPasswordState( +data class ResetIdentityPasswordState( val resetAction: AsyncAction, - val eventSink: (ResetKeyPasswordEvent) -> Unit, + val eventSink: (ResetIdentityPasswordEvent) -> Unit, ) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt similarity index 92% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordView.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt index d9339064f2..d64e451a9f 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetKeyPasswordView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt @@ -46,8 +46,8 @@ import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKe import io.element.android.libraries.ui.strings.CommonStrings @Composable -fun ResetKeyPasswordView( - state: ResetKeyPasswordState, +fun ResetIdentityPasswordView( + state: ResetIdentityPasswordState, onBack: () -> Unit, modifier: Modifier = Modifier, ) { @@ -63,7 +63,7 @@ fun ResetKeyPasswordView( Button( modifier = Modifier.fillMaxWidth(), text = stringResource(CommonStrings.action_reset_identity), - onClick = { state.eventSink(ResetKeyPasswordEvent.Reset(passwordState.value)) }, + onClick = { state.eventSink(ResetIdentityPasswordEvent.Reset(passwordState.value)) }, destructive = true, ) } @@ -74,7 +74,7 @@ fun ResetKeyPasswordView( } else if (state.resetAction.isFailure()) { ErrorDialog( content = stringResource(CommonStrings.error_unknown), - onDismiss = { state.eventSink(ResetKeyPasswordEvent.DismissError) } + onDismiss = { state.eventSink(ResetIdentityPasswordEvent.DismissError) } ) } } @@ -107,10 +107,10 @@ private fun Content(textFieldState: MutableState) { @PreviewsDayNight @Composable -internal fun ResetKeyPasswordViewPreview() { +internal fun ResetIdentityPasswordViewPreview() { ElementPreview { - ResetKeyPasswordView( - state = ResetKeyPasswordState( + ResetIdentityPasswordView( + state = ResetIdentityPasswordState( resetAction = AsyncAction.Uninitialized, eventSink = {} ), diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootEvent.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootEvent.kt similarity index 82% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootEvent.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootEvent.kt index 268228ac8b..a1ec4cbe82 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootEvent.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootEvent.kt @@ -16,7 +16,7 @@ package io.element.android.features.securebackup.impl.reset.root -sealed interface ResetKeyRootEvent { - data object Continue : ResetKeyRootEvent - data object DismissDialog : ResetKeyRootEvent +sealed interface ResetIdentityRootEvent { + data object Continue : ResetIdentityRootEvent + data object DismissDialog : ResetIdentityRootEvent } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootNode.kt similarity index 91% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootNode.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootNode.kt index b7171aaa7b..9fc5061ae2 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootNode.kt @@ -27,7 +27,7 @@ import io.element.android.anvilannotations.ContributesNode import io.element.android.libraries.di.SessionScope @ContributesNode(SessionScope::class) -class ResetKeyRootNode @AssistedInject constructor( +class ResetIdentityRootNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, ) : Node(buildContext, plugins = plugins) { @@ -35,13 +35,13 @@ class ResetKeyRootNode @AssistedInject constructor( fun onContinue() } - private val presenter = ResetKeyRootPresenter() + private val presenter = ResetIdentityRootPresenter() private val callback: Callback = plugins.filterIsInstance().first() @Composable override fun View(modifier: Modifier) { val state = presenter.present() - ResetKeyRootView( + ResetIdentityRootView( state = state, onContinue = callback::onContinue, onBack = ::navigateUp, diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootPresenter.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenter.kt similarity index 78% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootPresenter.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenter.kt index d2e3e5dc70..11c96e9ad8 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootPresenter.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenter.kt @@ -23,19 +23,19 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import io.element.android.libraries.architecture.Presenter -class ResetKeyRootPresenter : Presenter { +class ResetIdentityRootPresenter : Presenter { @Composable - override fun present(): ResetKeyRootState { + override fun present(): ResetIdentityRootState { var displayConfirmDialog by remember { mutableStateOf(false) } - fun handleEvent(event: ResetKeyRootEvent) { + fun handleEvent(event: ResetIdentityRootEvent) { displayConfirmDialog = when (event) { - ResetKeyRootEvent.Continue -> true - ResetKeyRootEvent.DismissDialog -> false + ResetIdentityRootEvent.Continue -> true + ResetIdentityRootEvent.DismissDialog -> false } } - return ResetKeyRootState( + return ResetIdentityRootState( displayConfirmationDialog = displayConfirmDialog, eventSink = ::handleEvent ) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootState.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootState.kt similarity index 89% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootState.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootState.kt index faaee64040..de1054c97f 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootState.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootState.kt @@ -16,7 +16,7 @@ package io.element.android.features.securebackup.impl.reset.root -data class ResetKeyRootState( +data class ResetIdentityRootState( val displayConfirmationDialog: Boolean, - val eventSink: (ResetKeyRootEvent) -> Unit, + val eventSink: (ResetIdentityRootEvent) -> Unit, ) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootStateProvider.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootStateProvider.kt similarity index 81% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootStateProvider.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootStateProvider.kt index 15299fa5ba..8d780343fe 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootStateProvider.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootStateProvider.kt @@ -18,14 +18,14 @@ package io.element.android.features.securebackup.impl.reset.root import androidx.compose.ui.tooling.preview.PreviewParameterProvider -class ResetKeyRootStateProvider : PreviewParameterProvider { - override val values: Sequence +class ResetIdentityRootStateProvider : PreviewParameterProvider { + override val values: Sequence get() = sequenceOf( - ResetKeyRootState( + ResetIdentityRootState( displayConfirmationDialog = false, eventSink = {} ), - ResetKeyRootState( + ResetIdentityRootState( displayConfirmationDialog = true, eventSink = {} ) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt similarity index 92% rename from features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootView.kt rename to features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt index cbeaa1a14e..8020aee5c6 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetKeyRootView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt @@ -43,8 +43,8 @@ import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.persistentListOf @Composable -fun ResetKeyRootView( - state: ResetKeyRootState, +fun ResetIdentityRootView( + state: ResetIdentityRootState, onContinue: () -> Unit, onBack: () -> Unit, ) { @@ -58,7 +58,7 @@ fun ResetKeyRootView( Button( modifier = Modifier.fillMaxWidth(), text = stringResource(id = CommonStrings.action_continue), - onClick = { state.eventSink(ResetKeyRootEvent.Continue) }, + onClick = { state.eventSink(ResetIdentityRootEvent.Continue) }, destructive = true, ) }, @@ -71,11 +71,11 @@ fun ResetKeyRootView( content = stringResource(CommonStrings.screen_reset_encryption_confirmation_alert_subtitle), submitText = stringResource(CommonStrings.screen_reset_encryption_confirmation_alert_action), onSubmitClick = { - state.eventSink(ResetKeyRootEvent.DismissDialog) + state.eventSink(ResetIdentityRootEvent.DismissDialog) onContinue() }, destructiveSubmit = true, - onDismiss = { state.eventSink(ResetKeyRootEvent.DismissDialog) } + onDismiss = { state.eventSink(ResetIdentityRootEvent.DismissDialog) } ) } } @@ -138,9 +138,9 @@ private fun Content() { @PreviewsDayNight @Composable -internal fun ResetKeyRootViewPreview(@PreviewParameter(ResetKeyRootStateProvider::class) state: ResetKeyRootState) { +internal fun ResetIdentityRootViewPreview(@PreviewParameter(ResetIdentityRootStateProvider::class) state: ResetIdentityRootState) { ElementPreview { - ResetKeyRootView( + ResetIdentityRootView( state = state, onContinue = {}, onBack = {}, diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTests.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTests.kt new file mode 100644 index 0000000000..6669d0cc90 --- /dev/null +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTests.kt @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset + +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService +import io.element.android.libraries.matrix.test.encryption.FakeIdentityPasswordResetHandle +import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService +import io.element.android.tests.testutils.lambda.lambdaRecorder +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class ResetIdentityFlowManagerTests { + @Test + fun `getResetHandle - emits a reset handle`() = runTest { + val startResetLambda = lambdaRecorder> { Result.success(FakeIdentityPasswordResetHandle()) } + val encryptionService = FakeEncryptionService(startIdentityResetLambda = startResetLambda) + val flowManager = createFlowManager(encryptionService = encryptionService) + + flowManager.getResetHandle().test { + assertThat(awaitItem().isLoading()).isTrue() + assertThat(awaitItem().isSuccess()).isTrue() + startResetLambda.assertions().isCalledOnce() + } + } + + @Test + fun `getResetHandle - om successful handle retrieval returns that same handle`() = runTest { + val startResetLambda = lambdaRecorder> { Result.success(FakeIdentityPasswordResetHandle()) } + val encryptionService = FakeEncryptionService(startIdentityResetLambda = startResetLambda) + val flowManager = createFlowManager(encryptionService = encryptionService) + + var result: AsyncData.Success? = null + flowManager.getResetHandle().test { + assertThat(awaitItem().isLoading()).isTrue() + result = awaitItem() as? AsyncData.Success + assertThat(result).isNotNull() + } + + flowManager.getResetHandle().test { + assertThat(awaitItem()).isSameInstanceAs(result) + } + } + + @Test + fun `getResetHandle - will fail if it receives a null reset handle`() = runTest { + val startResetLambda = lambdaRecorder> { Result.success(null) } + val encryptionService = FakeEncryptionService(startIdentityResetLambda = startResetLambda) + val flowManager = createFlowManager(encryptionService = encryptionService) + + flowManager.getResetHandle().test { + assertThat(awaitItem().isLoading()).isTrue() + assertThat(awaitItem().isFailure()).isTrue() + startResetLambda.assertions().isCalledOnce() + } + } + + @Test + fun `getResetHandle - fails gracefully when receiving an exception from the encryption service`() = runTest { + val startResetLambda = lambdaRecorder> { Result.failure(IllegalStateException("Failure")) } + val encryptionService = FakeEncryptionService(startIdentityResetLambda = startResetLambda) + val flowManager = createFlowManager(encryptionService = encryptionService) + + flowManager.getResetHandle().test { + assertThat(awaitItem().isLoading()).isTrue() + assertThat(awaitItem().isFailure()).isTrue() + startResetLambda.assertions().isCalledOnce() + } + } + + @Test + fun `cancel - resets the state and calls cancel on the reset handle`() = runTest { + val cancelLambda = lambdaRecorder { } + val resetHandle = FakeIdentityPasswordResetHandle(cancelLambda = cancelLambda) + val startResetLambda = lambdaRecorder> { Result.success(resetHandle) } + val encryptionService = FakeEncryptionService(startIdentityResetLambda = startResetLambda) + val flowManager = createFlowManager(encryptionService = encryptionService) + + flowManager.getResetHandle().test { + assertThat(awaitItem().isLoading()).isTrue() + assertThat(awaitItem().isSuccess()).isTrue() + + flowManager.cancel() + cancelLambda.assertions().isCalledOnce() + assertThat(awaitItem().isUninitialized()).isTrue() + } + } + + private fun TestScope.createFlowManager( + encryptionService: FakeEncryptionService = FakeEncryptionService(), + client: FakeMatrixClient = FakeMatrixClient(encryptionService = encryptionService), + sessionCoroutineScope: CoroutineScope = this, + sessionVerificationService: FakeSessionVerificationService = FakeSessionVerificationService(), + ) = ResetIdentityFlowManager( + matrixClient = client, + sessionCoroutineScope = sessionCoroutineScope, + sessionVerificationService = sessionVerificationService, + ) +} diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordPresenterTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordPresenterTest.kt new file mode 100644 index 0000000000..059983df3d --- /dev/null +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordPresenterTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.password + +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.test.encryption.FakeIdentityPasswordResetHandle +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.Test + +class ResetIdentityPasswordPresenterTest { + @Test + fun `present - initial state`() = runTest { + val presenter = createPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.resetAction.isUninitialized()).isTrue() + } + } + + @Test + fun `present - Reset event succeeds`() = runTest { + val resetLambda = lambdaRecorder> { _ -> Result.success(Unit) } + val resetHandle = FakeIdentityPasswordResetHandle(resetPasswordLambda = resetLambda) + val presenter = createPresenter(identityResetHandle = resetHandle) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(ResetIdentityPasswordEvent.Reset("password")) + assertThat(awaitItem().resetAction.isLoading()).isTrue() + assertThat(awaitItem().resetAction.isSuccess()).isTrue() + } + } + + @Test + fun `present - Reset event can fail gracefully`() = runTest { + val resetLambda = lambdaRecorder> { _ -> Result.failure(IllegalStateException("Failed")) } + val resetHandle = FakeIdentityPasswordResetHandle(resetPasswordLambda = resetLambda) + val presenter = createPresenter(identityResetHandle = resetHandle) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(ResetIdentityPasswordEvent.Reset("password")) + assertThat(awaitItem().resetAction.isLoading()).isTrue() + assertThat(awaitItem().resetAction.isFailure()).isTrue() + } + } + + @Test + fun `present - DismissError event resets the state`() = runTest { + val resetLambda = lambdaRecorder> { _ -> Result.failure(IllegalStateException("Failed")) } + val resetHandle = FakeIdentityPasswordResetHandle(resetPasswordLambda = resetLambda) + val presenter = createPresenter(identityResetHandle = resetHandle) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(ResetIdentityPasswordEvent.Reset("password")) + assertThat(awaitItem().resetAction.isLoading()).isTrue() + assertThat(awaitItem().resetAction.isFailure()).isTrue() + + initialState.eventSink(ResetIdentityPasswordEvent.DismissError) + assertThat(awaitItem().resetAction.isUninitialized()).isTrue() + } + } + + private fun TestScope.createPresenter( + identityResetHandle: FakeIdentityPasswordResetHandle = FakeIdentityPasswordResetHandle(), + ) = ResetIdentityPasswordPresenter( + identityPasswordResetHandle = identityResetHandle, + dispatchers = testCoroutineDispatchers(), + ) +} diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt new file mode 100644 index 0000000000..17029452db --- /dev/null +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.password + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performTextInput +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.tests.testutils.EnsureNeverCalled +import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.clickOn +import io.element.android.tests.testutils.ensureCalledOnce +import io.element.android.tests.testutils.pressBack +import io.element.android.tests.testutils.pressBackKey +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TestRule +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ResetIdentityPasswordViewTest { + @get:Rule + val rule = createAndroidComposeRule() + + @Test + fun `pressing the back HW button invokes the expected callback`() { + ensureCalledOnce { + rule.setResetPasswordView( + ResetIdentityPasswordState(resetAction = AsyncAction.Uninitialized, eventSink = {}), + onBack = it, + ) + rule.pressBackKey() + } + } + + @Test + fun `clicking on the back navigation button invokes the expected callback`() { + ensureCalledOnce { + rule.setResetPasswordView( + ResetIdentityPasswordState(resetAction = AsyncAction.Uninitialized, eventSink = {}), + onBack = it, + ) + rule.pressBack() + } + } + + @Test + fun `clicking 'Reset identity' confirms the reset`() { + val eventsRecorder = EventsRecorder() + rule.setResetPasswordView( + ResetIdentityPasswordState(resetAction = AsyncAction.Uninitialized, eventSink = eventsRecorder), + ) + rule.onNodeWithText("Password").performTextInput("A password") + + rule.clickOn(CommonStrings.action_reset_identity) + + eventsRecorder.assertSingle(ResetIdentityPasswordEvent.Reset("A password")) + } + + @Test + fun `clicking OK dismisses the error dialog`() { + val eventsRecorder = EventsRecorder() + rule.setResetPasswordView( + ResetIdentityPasswordState(resetAction = AsyncAction.Failure(IllegalStateException("A failure")), eventSink = eventsRecorder), + ) + rule.clickOn(CommonStrings.action_ok) + + eventsRecorder.assertSingle(ResetIdentityPasswordEvent.DismissError) + } +} + +private fun AndroidComposeTestRule.setResetPasswordView( + state: ResetIdentityPasswordState, + onBack: () -> Unit = EnsureNeverCalled(), +) { + setContent { + ResetIdentityPasswordView(state = state, onBack = onBack) + } +} diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenterTests.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenterTests.kt new file mode 100644 index 0000000000..5b669a0dc7 --- /dev/null +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenterTests.kt @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.root + +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class ResetIdentityRootPresenterTests { + @Test + fun `present - initial state`() = runTest { + val presenter = ResetIdentityRootPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.displayConfirmationDialog).isFalse() + } + } + + @Test + fun `present - Continue event displays the confirmation dialog`() = runTest { + val presenter = ResetIdentityRootPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(ResetIdentityRootEvent.Continue) + + assertThat(awaitItem().displayConfirmationDialog).isTrue() + } + } + + @Test + fun `present - DismissDialog event hides the confirmation dialog`() = runTest { + val presenter = ResetIdentityRootPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(ResetIdentityRootEvent.Continue) + assertThat(awaitItem().displayConfirmationDialog).isTrue() + + initialState.eventSink(ResetIdentityRootEvent.DismissDialog) + assertThat(awaitItem().displayConfirmationDialog).isFalse() + } + } +} diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTests.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTests.kt new file mode 100644 index 0000000000..9367b3c9e0 --- /dev/null +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTests.kt @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.root + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.tests.testutils.EnsureNeverCalled +import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.clickOn +import io.element.android.tests.testutils.ensureCalledOnce +import io.element.android.tests.testutils.pressBack +import io.element.android.tests.testutils.pressBackKey +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TestRule +import org.junit.runner.RunWith +import org.robolectric.annotation.Config + +@RunWith(AndroidJUnit4::class) +class ResetIdentityRootViewTests { + @get:Rule + val rule = createAndroidComposeRule() + + @Test + fun `pressing the back HW button invokes the expected callback`() { + ensureCalledOnce { + rule.setResetRootView( + ResetIdentityRootState(displayConfirmationDialog = false, eventSink = {}), + onBack = it, + ) + rule.pressBackKey() + } + } + + @Test + fun `clicking on the back navigation button invokes the expected callback`() { + ensureCalledOnce { + rule.setResetRootView( + ResetIdentityRootState(displayConfirmationDialog = false, eventSink = {}), + onBack = it, + ) + rule.pressBack() + } + } + + @Test + @Config(qualifiers = "h720dp") + fun `clicking Continue displays the confirmation dialog`() { + val eventsRecorder = EventsRecorder() + rule.setResetRootView( + ResetIdentityRootState(displayConfirmationDialog = false, eventSink = eventsRecorder), + ) + + rule.clickOn(CommonStrings.action_continue) + + eventsRecorder.assertSingle(ResetIdentityRootEvent.Continue) + } + + @Test + fun `clicking 'Yes, reset now' confirms the reset`() { + ensureCalledOnce { + rule.setResetRootView( + ResetIdentityRootState(displayConfirmationDialog = true, eventSink = {}), + onContinue = it, + ) + rule.clickOn(CommonStrings.screen_reset_encryption_confirmation_alert_action) + } + } + + @Test + fun `clicking Cancel dismisses the dialog`() { + val eventsRecorder = EventsRecorder() + rule.setResetRootView( + ResetIdentityRootState(displayConfirmationDialog = true, eventSink = eventsRecorder), + ) + + rule.clickOn(CommonStrings.action_cancel) + eventsRecorder.assertSingle(ResetIdentityRootEvent.DismissDialog) + } +} + +private fun AndroidComposeTestRule.setResetRootView( + state: ResetIdentityRootState, + onBack: () -> Unit = EnsureNeverCalled(), + onContinue: () -> Unit = EnsureNeverCalled(), +) { + setContent { + ResetIdentityRootView(state = state, onContinue = onContinue, onBack = onBack) + } +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt index 420940aefe..5afb81648b 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt @@ -16,7 +16,6 @@ package io.element.android.libraries.matrix.api.encryption -import io.element.android.libraries.matrix.api.core.UserId import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow @@ -90,10 +89,9 @@ interface IdentityPasswordResetHandle : IdentityResetHandle { * This method will block the coroutine it's running on and keep polling indefinitely until either the coroutine is cancelled, the [cancel] method is * called, or the identity is reset. * - * @param userId the user id of the user to reset the password for. * @param password the current password, which will be validated before the process takes place. */ - suspend fun resetPassword(userId: UserId, password: String): Result + suspend fun resetPassword(password: String): Result } /** diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt index 728fbede55..ae681b2771 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt @@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.impl.encryption import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.extensions.mapFailure +import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.BackupUploadState import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress @@ -55,6 +56,7 @@ internal class RustEncryptionService( private val dispatchers: CoroutineDispatchers, ) : EncryptionService { private val service: Encryption = client.encryption() + private val sessionId = SessionId(client.session().userId) private val enableRecoveryProgressMapper = EnableRecoveryProgressMapper() private val backupUploadStateMapper = BackupUploadStateMapper() @@ -201,6 +203,10 @@ internal class RustEncryptionService( } override suspend fun startIdentityReset(): Result { - return runCatching { service.resetIdentity()?.let(RustIdentityResetHandleFactory::create)?.getOrNull() } + return runCatching { + service.resetIdentity()?.let { handle -> + RustIdentityResetHandleFactory.create(sessionId, handle) + }?.getOrNull() + } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt index 0d51d7c4c2..c4c20eb7d6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt @@ -25,21 +25,25 @@ import org.matrix.rustcomponents.sdk.AuthDataPasswordDetails import org.matrix.rustcomponents.sdk.CrossSigningResetAuthType object RustIdentityResetHandleFactory { - fun create(identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle): Result { + fun create( + userId: UserId, + identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle + ): Result { return runCatching { when (val authType = identityResetHandle.authType()) { is CrossSigningResetAuthType.Oidc -> RustOidcIdentityResetHandle(identityResetHandle, authType.info.approvalUrl) // User interactive authentication (user + password) - CrossSigningResetAuthType.Uiaa -> RustPasswordIdentityResetHandle(identityResetHandle) + CrossSigningResetAuthType.Uiaa -> RustPasswordIdentityResetHandle(userId, identityResetHandle) } } } } class RustPasswordIdentityResetHandle( + private val userId: UserId, private val identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle, ) : IdentityPasswordResetHandle { - override suspend fun resetPassword(userId: UserId, password: String): Result { + override suspend fun resetPassword(password: String): Result { return runCatching { identityResetHandle.reset(AuthData.Password(AuthDataPasswordDetails(userId.value, password))) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt index 6b3eabd102..69087163d2 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt @@ -16,7 +16,6 @@ package io.element.android.libraries.matrix.test.encryption -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle @@ -35,11 +34,11 @@ class FakeIdentityOidcResetHandle( } class FakeIdentityPasswordResetHandle( - var resetPasswordLambda: (UserId, String) -> Result = { _, _ -> error("Not implemented") }, + var resetPasswordLambda: (String) -> Result = { _ -> error("Not implemented") }, var cancelLambda: () -> Unit = { error("Not implemented") }, ) : IdentityPasswordResetHandle { - override suspend fun resetPassword(userId: UserId, password: String): Result { - return resetPasswordLambda(userId, password) + override suspend fun resetPassword(password: String): Result { + return resetPasswordLambda(password) } override suspend fun cancel() { From 5239e5ce81f477c1ad25af9c4626657ebe511fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 12 Aug 2024 12:41:04 +0200 Subject: [PATCH 100/186] Fix lint issues --- .../io/element/android/appnav/RootFlowNode.kt | 2 +- .../impl/reset/ResetIdentityFlowNode.kt | 2 +- .../reset/password/ResetIdentityPasswordNode.kt | 1 - .../reset/password/ResetIdentityPasswordView.kt | 14 +++++++++----- .../impl/reset/root/ResetIdentityRootNode.kt | 1 + .../impl/reset/root/ResetIdentityRootView.kt | 2 ++ ...rTests.kt => ResetIdentityRootPresenterTest.kt} | 2 +- .../android/libraries/matrix/api/MatrixClient.kt | 1 - .../libraries/oidc/impl/DefaultOidcEntryPoint.kt | 2 +- .../libraries/oidc/impl/webview/OidcPresenter.kt | 2 +- 10 files changed, 17 insertions(+), 12 deletions(-) rename features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/{ResetIdentityRootPresenterTests.kt => ResetIdentityRootPresenterTest.kt} (98%) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt index b651f4d77c..87e08b6bb9 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt @@ -56,9 +56,9 @@ import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.api.permalink.PermalinkData -import io.element.android.libraries.sessionstorage.api.LoggedInState import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oidc.api.OidcActionFlow +import io.element.android.libraries.sessionstorage.api.LoggedInState import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt index 0f0278cb66..be538a8665 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt @@ -66,7 +66,7 @@ class ResetIdentityFlowNode @AssistedInject constructor( buildContext = buildContext, plugins = plugins, ) { - interface Callback: Plugin { + interface Callback : Plugin { fun onDone() } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt index 7397361b03..0f158e04c2 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt @@ -36,7 +36,6 @@ class ResetIdentityPasswordNode @AssistedInject constructor( @Assisted plugins: List, private val coroutineDispatchers: CoroutineDispatchers, ) : Node(buildContext, plugins = plugins) { - data class Inputs(val handle: IdentityPasswordResetHandle) : NodeInputs private val presenter by lazy { diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt index d64e451a9f..a43ff8092f 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt @@ -18,7 +18,6 @@ package io.element.android.features.securebackup.impl.reset.password import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -58,7 +57,12 @@ fun ResetIdentityPasswordView( title = stringResource(CommonStrings.screen_reset_encryption_password_title), subTitle = stringResource(CommonStrings.screen_reset_encryption_password_subtitle), onBackClick = onBack, - content = { Content(textFieldState = passwordState) }, + content = { + Content( + text = passwordState.value, + onTextChange = { passwordState.value = it } + ) + }, buttons = { Button( modifier = Modifier.fillMaxWidth(), @@ -80,14 +84,14 @@ fun ResetIdentityPasswordView( } @Composable -private fun Content(textFieldState: MutableState) { +private fun Content(text: String, onTextChange: (String) -> Unit) { var showPassword by remember { mutableStateOf(false) } OutlinedTextField( modifier = Modifier .fillMaxWidth() .onTabOrEnterKeyFocusNext(LocalFocusManager.current), - value = textFieldState.value, - onValueChange = { text -> textFieldState.value = text }, + value = text, + onValueChange = onTextChange, label = { Text(stringResource(CommonStrings.common_password)) }, placeholder = { Text(stringResource(CommonStrings.screen_reset_encryption_password_placeholder)) }, singleLine = true, diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootNode.kt index 9fc5061ae2..3dd9876fc0 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootNode.kt @@ -42,6 +42,7 @@ class ResetIdentityRootNode @AssistedInject constructor( override fun View(modifier: Modifier) { val state = presenter.present() ResetIdentityRootView( + modifier = modifier, state = state, onContinue = callback::onContinue, onBack = ::navigateUp, diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt index 8020aee5c6..4e0457836f 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt @@ -47,8 +47,10 @@ fun ResetIdentityRootView( state: ResetIdentityRootState, onContinue: () -> Unit, onBack: () -> Unit, + modifier: Modifier = Modifier, ) { FlowStepPage( + modifier = modifier, iconStyle = BigIcon.Style.AlertSolid, title = stringResource(io.element.android.libraries.ui.strings.R.string.screen_encryption_reset_title), subTitle = stringResource(io.element.android.libraries.ui.strings.R.string.screen_encryption_reset_subtitle), diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenterTests.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenterTest.kt similarity index 98% rename from features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenterTests.kt rename to features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenterTest.kt index 5b669a0dc7..feb00bf4de 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenterTests.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootPresenterTest.kt @@ -23,7 +23,7 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test -class ResetIdentityRootPresenterTests { +class ResetIdentityRootPresenterTest { @Test fun `present - initial state`() = runTest { val presenter = ResetIdentityRootPresenter() 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 0591e794ed..3209d49e03 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 @@ -41,7 +41,6 @@ import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService -import io.element.android.libraries.sessionstorage.api.LoginType import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow diff --git a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcEntryPoint.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcEntryPoint.kt index 1a8ce960c5..185c27bf19 100644 --- a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcEntryPoint.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcEntryPoint.kt @@ -24,8 +24,8 @@ import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTa import io.element.android.libraries.architecture.createNode import io.element.android.libraries.di.AppScope import io.element.android.libraries.matrix.api.auth.OidcDetails -import io.element.android.libraries.oidc.impl.webview.OidcNode import io.element.android.libraries.oidc.api.OidcEntryPoint +import io.element.android.libraries.oidc.impl.webview.OidcNode import javax.inject.Inject @ContributesBinding(AppScope::class) diff --git a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenter.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenter.kt index 853a9b584c..5e886644f6 100644 --- a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenter.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenter.kt @@ -25,11 +25,11 @@ import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.oidc.api.OidcAction import kotlinx.coroutines.launch class OidcPresenter @AssistedInject constructor( From ae18efd2a9c3d484cdbae9caf541461647561696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 12 Aug 2024 12:54:51 +0200 Subject: [PATCH 101/186] Fix `OidcView` preview --- .../libraries/oidc/impl/webview/OidcView.kt | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt index 56a04cb0ea..0ba9d4ea52 100644 --- a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt +++ b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt @@ -27,6 +27,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.viewinterop.AndroidView import io.element.android.libraries.core.bool.orFalse @@ -45,6 +46,7 @@ fun OidcView( onNavigateBack: () -> Unit, modifier: Modifier = Modifier, ) { + val isPreview = LocalInspectionMode.current val oidcUrlParser = remember { OidcUrlParser() } var webView by remember { mutableStateOf(null) } fun shouldOverrideUrl(url: String): Boolean { @@ -86,16 +88,18 @@ fun OidcView( modifier = Modifier.padding(contentPadding), factory = { context -> WebView(context).apply { - webViewClient = oidcWebViewClient - settings.apply { - @SuppressLint("SetJavaScriptEnabled") - javaScriptEnabled = true - allowContentAccess = true - allowFileAccess = true - databaseEnabled = true - domStorageEnabled = true + if (!isPreview) { + webViewClient = oidcWebViewClient + settings.apply { + @SuppressLint("SetJavaScriptEnabled") + javaScriptEnabled = true + allowContentAccess = true + allowFileAccess = true + databaseEnabled = true + domStorageEnabled = true + } + loadUrl(state.oidcDetails.url) } - loadUrl(state.oidcDetails.url) }.also { webView = it } From 300df0c620bc2b5cd6231f105b9d2ab98a11b053 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 12 Aug 2024 11:06:00 +0000 Subject: [PATCH 102/186] Update screenshots --- .../features.login.impl.oidc.webview_OidcView_Day_0_en.png | 3 --- .../features.login.impl.oidc.webview_OidcView_Day_1_en.png | 3 --- .../features.login.impl.oidc.webview_OidcView_Night_0_en.png | 3 --- .../features.login.impl.oidc.webview_OidcView_Night_1_en.png | 3 --- ...impl.reset.password_ResetIdentityPasswordView_Day_0_en.png | 3 +++ ...pl.reset.password_ResetIdentityPasswordView_Night_0_en.png | 3 +++ ...ebackup.impl.reset.root_ResetIdentityRootView_Day_0_en.png | 3 +++ ...ebackup.impl.reset.root_ResetIdentityRootView_Day_1_en.png | 3 +++ ...ackup.impl.reset.root_ResetIdentityRootView_Night_0_en.png | 3 +++ ...ackup.impl.reset.root_ResetIdentityRootView_Night_1_en.png | 3 +++ ...ures.verifysession.impl_VerifySelfSessionView_Day_0_en.png | 4 ++-- ...ures.verifysession.impl_VerifySelfSessionView_Day_1_en.png | 4 ++-- ...ures.verifysession.impl_VerifySelfSessionView_Day_7_en.png | 4 ++-- ...ures.verifysession.impl_VerifySelfSessionView_Day_8_en.png | 4 ++-- ...ures.verifysession.impl_VerifySelfSessionView_Day_9_en.png | 4 ++-- ...es.verifysession.impl_VerifySelfSessionView_Night_0_en.png | 4 ++-- ...es.verifysession.impl_VerifySelfSessionView_Night_1_en.png | 4 ++-- ...es.verifysession.impl_VerifySelfSessionView_Night_7_en.png | 4 ++-- ...es.verifysession.impl_VerifySelfSessionView_Night_8_en.png | 4 ++-- ...es.verifysession.impl_VerifySelfSessionView_Night_9_en.png | 4 ++-- .../images/libraries.oidc.impl.webview_OidcView_Day_0_en.png | 3 +++ .../images/libraries.oidc.impl.webview_OidcView_Day_1_en.png | 3 +++ .../libraries.oidc.impl.webview_OidcView_Night_0_en.png | 3 +++ .../libraries.oidc.impl.webview_OidcView_Night_1_en.png | 3 +++ 24 files changed, 50 insertions(+), 32 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Day_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Night_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Night_1_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Day_0_en.png deleted file mode 100644 index 1022157a43..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:38b4c852a4bb957a10e24a72b70d7edd89a921983a9426592dc1fc53c1d54d99 -size 5450 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Day_1_en.png deleted file mode 100644 index 39071712f4..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Day_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9cdc07cc74bf427e7ae0244b97543f65aecb6b2f8fee7958d18906d333b868b8 -size 8848 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Night_0_en.png deleted file mode 100644 index 15ff876cf4..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a0c39aabac135aa3954ac881a43cc2bd79a2e357ec76f9aa46351b2985c17d73 -size 5437 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Night_1_en.png deleted file mode 100644 index f99c8e006d..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.oidc.webview_OidcView_Night_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c773553943c9728f1e80b6ca6491c9c8c50f9394f3bd1cb430abb24029a3f926 -size 7791 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png new file mode 100644 index 0000000000..e82254087f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:688c50e8f414a6bdb3dd0e718f8de426badcea744509069a3023dfc2d2e59816 +size 29040 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png new file mode 100644 index 0000000000..9b905f24c2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:061cebcf9a9646fb6c962272692fa123d60b9e17cd6b29b581c17ef125880a9e +size 28166 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en.png new file mode 100644 index 0000000000..499713a15d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9b7a1e2d20171a78da4ce4f590372e1d84f9624c4d56a011e74f91105c09f36 +size 79989 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en.png new file mode 100644 index 0000000000..6bc0eec9c0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43f2eb2cb1f1b986b58d2614c892f2f7f15f1b696a656165ba1f8644f7759476 +size 62679 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en.png new file mode 100644 index 0000000000..8685aa5e42 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c3c38d62929774fe6e6e003f656efbeec1f675b5dbb9994a917c4978f64d61a9 +size 78280 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en.png new file mode 100644 index 0000000000..e79557dae6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08e5a9d4e1bc45e9411b74c7277f34fa0ba8d46fdd1556b65b9c50cc78f1468e +size 60595 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_0_en.png index b5f11147ba..cf48a305b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45548cd4afaac73a72ab4738c099506eb9dead138e8e0cf5668a75c4948b81f6 -size 26027 +oid sha256:ee9c90a91ef8703c4878ea9314121ad8343dd3392c051e7e3e3079198a32ef99 +size 30555 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_1_en.png index a989b3b474..623f4d1906 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88f3de0736a207057ce0e71fea632e5197874d93045e87443a957ef0da64b8bd -size 22760 +oid sha256:0ee7ae6c83491b5cd52582a8b66e916b4b9b038427f7b7e9e02320bb0f210615 +size 22795 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_7_en.png index 4a5ee01fb8..a2d07ed6a4 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:146a2a2439de11035332340ce27e622ff20b661d600fc2977d1f82deb81d0f21 -size 24828 +oid sha256:ce48c81c355317abd6b9de4600e86492c3acde2807ca3572e064b61abc06239c +size 29426 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_8_en.png index a4cde41390..69eb60569f 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:281e08f29d84da5c1e7c01d701bf5d8f415b6d80fb8a1298742d6e629314a7d8 -size 21186 +oid sha256:4d9810f3b326a05492c870ef22dbceec19112dba8beaa000066504cc96d1387a +size 23913 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_9_en.png index 4479a39460..0bd44d7bc8 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd68268fbc334f92f66413c8f63d9013468f6fa95d5b6264fdfe52e50637399e -size 26627 +oid sha256:892825ecd6a28010a152463e3a6e04ab50504e62d71b24944b144cb897fe3af2 +size 26626 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_0_en.png index 6ec093bbc8..31ba47d4a4 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf610f5f758e65ae67836a2b40924e966a8add94fd00605c89ef75ddbd3bf22c -size 25324 +oid sha256:453cab91aa056f3536c899354a2fb5de21519e7dce3d5675b1cbca702000e2c1 +size 29602 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_1_en.png index fddd555a33..8169f8b008 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2ed85817f1d95d1259e07aa566ede6d40360a688e29c0c463378770dd091540 -size 22003 +oid sha256:9653f24a7ba32ad19feb7c79a8fa5fc0f54e027f28b70c7e841fed77a682b129 +size 22051 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_7_en.png index 130cf67cf4..39ce0ef07f 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:354c1daceebd169b35a6db0173c954a3425c534156fdc662edfba4d710f51a49 -size 24155 +oid sha256:c21120a08c871c7f64952c20be2c90b28590901f8e52893702775b6b2f176892 +size 28524 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_8_en.png index 4c87611ada..7d1bfb8eab 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d6ce5c3b44127d5d661ac450ea2cf48617e81e4ae40dfb6d9a5cf89f3591800 -size 20598 +oid sha256:1e46ffc3c3679eb5490d01c34d02314bae5611a7b10fb3c758331a28ae78f065 +size 23267 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_9_en.png index 89268c76ed..6b5f9e58f8 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee39cc4f450e906a2e11ddb13ce4913ca442fa9bca8c95a7a50a9e51fbe2b3f6 -size 25981 +oid sha256:396cbf209b0b899a0f874556d4e47a8204aa9ff1cff69e464b91e09f389488c1 +size 25946 diff --git a/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Day_0_en.png new file mode 100644 index 0000000000..785f56af7f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:154a56d848cc735efc25274052ce92b1a20bc8f80f75e91d0d4cfc7d488cd246 +size 5874 diff --git a/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Day_1_en.png new file mode 100644 index 0000000000..ae8924e66e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0915d4781155524bece1db737050ceb78ef76128da39b339fd67dd4a2a4dd79d +size 9229 diff --git a/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Night_0_en.png new file mode 100644 index 0000000000..c41c1c7921 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2dd3462935091cfe022f0e6fc71b082eed7dab4769def13398a81a90f871b61a +size 5807 diff --git a/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Night_1_en.png new file mode 100644 index 0000000000..98b81898ef --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.oidc.impl.webview_OidcView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7cd23334c15b9039cbf0924a82703035b4498e67489418e5244cf2df576af9c +size 8111 From c02f0135f8b6b5cc4de63d31c99c9fd268467b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 12 Aug 2024 13:59:33 +0200 Subject: [PATCH 103/186] Fix vertical position for the primary button in `VerifySelfSessionView` --- .../features/verifysession/impl/VerifySelfSessionView.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt index f1c169b193..878030d9ec 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt @@ -54,6 +54,7 @@ import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.ButtonSize import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton @@ -260,6 +261,7 @@ private fun BottomMenu( onClick = onEnterRecoveryKey, ) } + // This option should always be displayed TextButton( modifier = Modifier.fillMaxWidth(), text = stringResource(R.string.screen_identity_confirmation_cannot_confirm), @@ -303,6 +305,8 @@ private fun BottomMenu( onClick = {}, showProgress = true, ) + // Placeholder so the 1st button keeps its vertical position + Spacer(modifier = Modifier.height(40.dp)) } } is FlowStep.Verifying -> { @@ -336,6 +340,8 @@ private fun BottomMenu( text = stringResource(CommonStrings.action_continue), onClick = onFinish, ) + // Placeholder so the 1st button keeps its vertical position + Spacer(modifier = Modifier.height(48.dp)) } } is FlowStep.Skipped -> return From 5e3e1271b48510f2cc665a376a878f7c91e52593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 12 Aug 2024 13:59:42 +0200 Subject: [PATCH 104/186] Fix Konsist failures --- ...ntityFlowManagerTests.kt => ResetIdentityFlowManagerTest.kt} | 2 +- ...setIdentityRootViewTests.kt => ResetIdentityRootViewTest.kt} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/{ResetIdentityFlowManagerTests.kt => ResetIdentityFlowManagerTest.kt} (99%) rename features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/{ResetIdentityRootViewTests.kt => ResetIdentityRootViewTest.kt} (99%) diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTests.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTest.kt similarity index 99% rename from features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTests.kt rename to features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTest.kt index 6669d0cc90..3a1e1898e3 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTests.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTest.kt @@ -30,7 +30,7 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test -class ResetIdentityFlowManagerTests { +class ResetIdentityFlowManagerTest { @Test fun `getResetHandle - emits a reset handle`() = runTest { val startResetLambda = lambdaRecorder> { Result.success(FakeIdentityPasswordResetHandle()) } diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTests.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt similarity index 99% rename from features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTests.kt rename to features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt index 9367b3c9e0..8d14618fe8 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTests.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt @@ -34,7 +34,7 @@ import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) -class ResetIdentityRootViewTests { +class ResetIdentityRootViewTest { @get:Rule val rule = createAndroidComposeRule() From d40f5bda12e182a34da733f806dc37c8d3427408 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 12 Aug 2024 12:12:43 +0000 Subject: [PATCH 105/186] Update screenshots --- ...ures.verifysession.impl_VerifySelfSessionView_Day_1_en.png | 4 ++-- ...ures.verifysession.impl_VerifySelfSessionView_Day_9_en.png | 4 ++-- ...es.verifysession.impl_VerifySelfSessionView_Night_1_en.png | 4 ++-- ...es.verifysession.impl_VerifySelfSessionView_Night_9_en.png | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_1_en.png index 623f4d1906..bfef3aada5 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ee7ae6c83491b5cd52582a8b66e916b4b9b038427f7b7e9e02320bb0f210615 -size 22795 +oid sha256:a4b44b23029dd1ff76a082a29c0b39584a1e20c92795eb4815d632608abd2858 +size 22702 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_9_en.png index 0bd44d7bc8..4479a39460 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:892825ecd6a28010a152463e3a6e04ab50504e62d71b24944b144cb897fe3af2 -size 26626 +oid sha256:cd68268fbc334f92f66413c8f63d9013468f6fa95d5b6264fdfe52e50637399e +size 26627 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_1_en.png index 8169f8b008..89dcb3654d 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9653f24a7ba32ad19feb7c79a8fa5fc0f54e027f28b70c7e841fed77a682b129 -size 22051 +oid sha256:f468a4a9140c4dc23ab3d394049f59b86f0ca2f332bee50abf8eaa0acce166b5 +size 22030 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_9_en.png index 6b5f9e58f8..89268c76ed 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl_VerifySelfSessionView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:396cbf209b0b899a0f874556d4e47a8204aa9ff1cff69e464b91e09f389488c1 -size 25946 +oid sha256:ee39cc4f450e906a2e11ddb13ce4913ca442fa9bca8c95a7a50a9e51fbe2b3f6 +size 25981 From f41e42d611e1f6b23a302ce72c46420206b35bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 12 Aug 2024 15:32:47 +0200 Subject: [PATCH 106/186] Remove unused import --- .../android/features/verifysession/impl/VerifySelfSessionView.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt index 878030d9ec..446114752e 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt @@ -54,7 +54,6 @@ import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button -import io.element.android.libraries.designsystem.theme.components.ButtonSize import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton From d5eb71ab0b183db4875c77be3240290c9525413a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 13 Aug 2024 08:54:56 +0200 Subject: [PATCH 107/186] Add an extra test --- .../reset/ResetIdentityFlowManagerTest.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTest.kt index 3a1e1898e3..eb33fe5c36 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManagerTest.kt @@ -20,13 +20,16 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle +import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.matrix.test.encryption.FakeIdentityPasswordResetHandle import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Test @@ -106,6 +109,32 @@ class ResetIdentityFlowManagerTest { } } + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `whenResetIsDone - will trigger the lambda when verification status is verified`() = runTest { + val verificationService = FakeSessionVerificationService() + val flowManager = createFlowManager(sessionVerificationService = verificationService) + var isDone = false + + flowManager.whenResetIsDone { + isDone = true + } + + assertThat(isDone).isFalse() + + verificationService.emitVerifiedStatus(SessionVerifiedStatus.Unknown) + advanceUntilIdle() + assertThat(isDone).isFalse() + + verificationService.emitVerifiedStatus(SessionVerifiedStatus.NotVerified) + advanceUntilIdle() + assertThat(isDone).isFalse() + + verificationService.emitVerifiedStatus(SessionVerifiedStatus.Verified) + advanceUntilIdle() + assertThat(isDone).isTrue() + } + private fun TestScope.createFlowManager( encryptionService: FakeEncryptionService = FakeEncryptionService(), client: FakeMatrixClient = FakeMatrixClient(encryptionService = encryptionService), From ca81e466ce8e642375ff8f2d5c4acba48f42e6df Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:18:38 +0000 Subject: [PATCH 108/186] Update dependency io.sentry:sentry-android to v7.14.0 (#3302) 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 a5252a217c..5afd73b9ce 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -187,7 +187,7 @@ play_services_oss_licenses = "com.google.android.gms:play-services-oss-licenses: # Analytics posthog = "com.posthog:posthog-android:3.5.0" -sentry = "io.sentry:sentry-android:7.13.0" +sentry = "io.sentry:sentry-android:7.14.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.23.1" From 8a1e333aa790b976bfbc7f2a289c5ccef678825c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 14 Aug 2024 16:53:50 +0200 Subject: [PATCH 109/186] Fix most review comments --- .../impl/reset/ResetIdentityFlowManager.kt | 7 ++- .../impl/reset/ResetIdentityFlowNode.kt | 48 +++++++++++-------- .../password/ResetIdentityPasswordNode.kt | 10 ++-- .../ResetIdentityPasswordStateProvider.kt | 38 +++++++++++++++ .../password/ResetIdentityPasswordView.kt | 40 +++++++++------- .../impl/reset/root/ResetIdentityRootView.kt | 19 ++++---- .../impl/src/main/res/values/localazy.xml | 13 +++++ .../password/ResetIdentityPasswordViewTest.kt | 4 +- .../reset/root/ResetIdentityRootViewTest.kt | 3 +- .../test/encryption/FakeEncryptionService.kt | 3 +- libraries/oidc/api/build.gradle.kts | 2 +- libraries/oidc/impl/build.gradle.kts | 10 +--- .../src/main/res/values/localazy.xml | 12 ----- tools/localazy/config.json | 5 +- 14 files changed, 136 insertions(+), 78 deletions(-) create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordStateProvider.kt diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt index 3425ca90be..16850890a7 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowManager.kt @@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.filterIsInstance @@ -37,9 +38,10 @@ class ResetIdentityFlowManager @Inject constructor( ) { private val resetHandleFlow: MutableStateFlow> = MutableStateFlow(AsyncData.Uninitialized) val currentHandleFlow: StateFlow> = resetHandleFlow + private var whenResetIsDoneWaitingJob: Job? = null fun whenResetIsDone(block: () -> Unit) { - sessionCoroutineScope.launch { + whenResetIsDoneWaitingJob = sessionCoroutineScope.launch { sessionVerificationService.sessionVerifiedStatus.filterIsInstance().first() block() } @@ -70,5 +72,8 @@ class ResetIdentityFlowManager @Inject constructor( suspend fun cancel() { currentHandleFlow.value.dataOrNull()?.cancel() resetHandleFlow.value = AsyncData.Uninitialized + + whenResetIsDoneWaitingJob?.cancel() + whenResetIsDoneWaitingJob = null } } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt index be538a8665..50dcc2dd12 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt @@ -23,6 +23,7 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.window.DialogProperties import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import com.bumble.appyx.core.modality.BuildContext @@ -45,14 +46,13 @@ import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle -import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle import io.element.android.libraries.oidc.api.OidcEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.filterIsInstance -import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize +import timber.log.Timber @ContributesNode(SessionScope::class) class ResetIdentityFlowNode @AssistedInject constructor( @@ -94,7 +94,7 @@ class ResetIdentityFlowNode @AssistedInject constructor( lifecycle.addObserver(object : DefaultLifecycleObserver { override fun onStart(owner: LifecycleOwner) { // If the custom tab was opened, we need to cancel the reset job - // when we come back to the node if it the reset wasn't successful + // when we come back to the node if the reset wasn't successful cancelResetJob() } @@ -129,22 +129,29 @@ class ResetIdentityFlowNode @AssistedInject constructor( } private fun CoroutineScope.startReset() = launch { - val handle = resetIdentityFlowManager.getResetHandle() - .filterIsInstance>() - .first() - .data - - when (handle) { - is IdentityOidcResetHandle -> { - if (oidcEntryPoint.canUseCustomTab()) { - activity.openUrlInChromeCustomTab(null, false, handle.url) - } else { - backstack.push(NavTarget.ResetOidc(handle.url)) + resetIdentityFlowManager.getResetHandle() + .collectLatest { state -> + when (state) { + is AsyncData.Failure -> { + cancelResetJob() + Timber.e(state.error, "Could not load the reset identity handle.") + } + is AsyncData.Success -> { + when (val handle = state.data) { + is IdentityOidcResetHandle -> { + if (oidcEntryPoint.canUseCustomTab()) { + activity.openUrlInChromeCustomTab(null, false, handle.url) + } else { + backstack.push(NavTarget.ResetOidc(handle.url)) + } + resetJob = launch { handle.resetOidc() } + } + is IdentityPasswordResetHandle -> backstack.push(NavTarget.ResetPassword) + } + } + else -> Unit } - resetJob = launch { handle.resetOidc() } } - is IdentityPasswordResetHandle -> backstack.push(NavTarget.ResetPassword) - } } private fun cancelResetJob() { @@ -162,7 +169,10 @@ class ResetIdentityFlowNode @AssistedInject constructor( val startResetState by resetIdentityFlowManager.currentHandleFlow.collectAsState() if (startResetState.isLoading()) { - ProgressDialog() + ProgressDialog( + properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = true), + onDismissRequest = { cancelResetJob() } + ) } BackstackView(modifier) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt index 0f158e04c2..75d487d00e 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordNode.kt @@ -34,14 +34,14 @@ import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetH class ResetIdentityPasswordNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val coroutineDispatchers: CoroutineDispatchers, + coroutineDispatchers: CoroutineDispatchers, ) : Node(buildContext, plugins = plugins) { data class Inputs(val handle: IdentityPasswordResetHandle) : NodeInputs - private val presenter by lazy { - val inputs = inputs() - ResetIdentityPasswordPresenter(inputs.handle, dispatchers = coroutineDispatchers) - } + private val presenter = ResetIdentityPasswordPresenter( + identityPasswordResetHandle = inputs().handle, + dispatchers = coroutineDispatchers + ) @Composable override fun View(modifier: Modifier) { diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordStateProvider.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordStateProvider.kt new file mode 100644 index 0000000000..1a1e768426 --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordStateProvider.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.reset.password + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.AsyncAction + +class ResetIdentityPasswordStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aResetIdentityPasswordState(), + aResetIdentityPasswordState(resetAction = AsyncAction.Loading), + aResetIdentityPasswordState(resetAction = AsyncAction.Success(Unit)), + aResetIdentityPasswordState(resetAction = AsyncAction.Failure(IllegalStateException("Failed"))), + ) +} + +private fun aResetIdentityPasswordState( + resetAction: AsyncAction = AsyncAction.Uninitialized, + eventSink: (ResetIdentityPasswordEvent) -> Unit = {}, +) = ResetIdentityPasswordState( + resetAction = resetAction, + eventSink = eventSink, +) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt index a43ff8092f..074752ddea 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt @@ -27,12 +27,12 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.libraries.architecture.AsyncAction +import io.element.android.features.securebackup.impl.R import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage import io.element.android.libraries.designsystem.components.BigIcon import io.element.android.libraries.designsystem.components.ProgressDialog -import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.form.textFieldState import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -54,13 +54,19 @@ fun ResetIdentityPasswordView( FlowStepPage( modifier = modifier, iconStyle = BigIcon.Style.Default(CompoundIcons.LockSolid()), - title = stringResource(CommonStrings.screen_reset_encryption_password_title), - subTitle = stringResource(CommonStrings.screen_reset_encryption_password_subtitle), + title = stringResource(R.string.screen_reset_encryption_password_title), + subTitle = stringResource(R.string.screen_reset_encryption_password_subtitle), onBackClick = onBack, content = { Content( text = passwordState.value, - onTextChange = { passwordState.value = it } + onTextChange = { newText -> + if (state.resetAction.isFailure()) { + state.eventSink(ResetIdentityPasswordEvent.DismissError) + } + passwordState.value = newText + }, + hasError = state.resetAction.isFailure(), ) }, buttons = { @@ -69,22 +75,19 @@ fun ResetIdentityPasswordView( text = stringResource(CommonStrings.action_reset_identity), onClick = { state.eventSink(ResetIdentityPasswordEvent.Reset(passwordState.value)) }, destructive = true, + enabled = passwordState.value.isNotEmpty(), ) } ) + // On success we need to wait until the screen is automatically dismissed, so we keep the progress dialog if (state.resetAction.isLoading() || state.resetAction.isSuccess()) { ProgressDialog() - } else if (state.resetAction.isFailure()) { - ErrorDialog( - content = stringResource(CommonStrings.error_unknown), - onDismiss = { state.eventSink(ResetIdentityPasswordEvent.DismissError) } - ) } } @Composable -private fun Content(text: String, onTextChange: (String) -> Unit) { +private fun Content(text: String, onTextChange: (String) -> Unit, hasError: Boolean) { var showPassword by remember { mutableStateOf(false) } OutlinedTextField( modifier = Modifier @@ -93,7 +96,7 @@ private fun Content(text: String, onTextChange: (String) -> Unit) { value = text, onValueChange = onTextChange, label = { Text(stringResource(CommonStrings.common_password)) }, - placeholder = { Text(stringResource(CommonStrings.screen_reset_encryption_password_placeholder)) }, + placeholder = { Text(stringResource(R.string.screen_reset_encryption_password_placeholder)) }, singleLine = true, visualTransformation = if (showPassword) VisualTransformation.None else PasswordVisualTransformation(), trailingIcon = { @@ -105,19 +108,22 @@ private fun Content(text: String, onTextChange: (String) -> Unit) { IconButton(onClick = { showPassword = !showPassword }) { Icon(imageVector = image, description) } + }, + isError = hasError, + supportingText = if (hasError) { + { Text(stringResource(R.string.screen_reset_encryption_password_error)) } + } else { + null } ) } @PreviewsDayNight @Composable -internal fun ResetIdentityPasswordViewPreview() { +internal fun ResetIdentityPasswordViewPreview(@PreviewParameter(ResetIdentityPasswordStateProvider::class) state: ResetIdentityPasswordState) { ElementPreview { ResetIdentityPasswordView( - state = ResetIdentityPasswordState( - resetAction = AsyncAction.Uninitialized, - eventSink = {} - ), + state = state, onBack = {} ) } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt index 4e0457836f..9983f06b44 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootView.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.securebackup.impl.R import io.element.android.libraries.designsystem.atomic.organisms.InfoListItem import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrganism import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage @@ -52,8 +53,8 @@ fun ResetIdentityRootView( FlowStepPage( modifier = modifier, iconStyle = BigIcon.Style.AlertSolid, - title = stringResource(io.element.android.libraries.ui.strings.R.string.screen_encryption_reset_title), - subTitle = stringResource(io.element.android.libraries.ui.strings.R.string.screen_encryption_reset_subtitle), + title = stringResource(R.string.screen_encryption_reset_title), + subTitle = stringResource(R.string.screen_encryption_reset_subtitle), isScrollable = true, content = { Content() }, buttons = { @@ -69,9 +70,9 @@ fun ResetIdentityRootView( if (state.displayConfirmationDialog) { ConfirmationDialog( - title = stringResource(CommonStrings.screen_reset_encryption_confirmation_alert_title), - content = stringResource(CommonStrings.screen_reset_encryption_confirmation_alert_subtitle), - submitText = stringResource(CommonStrings.screen_reset_encryption_confirmation_alert_action), + title = stringResource(R.string.screen_reset_encryption_confirmation_alert_title), + content = stringResource(R.string.screen_reset_encryption_confirmation_alert_subtitle), + submitText = stringResource(R.string.screen_reset_encryption_confirmation_alert_action), onSubmitClick = { state.eventSink(ResetIdentityRootEvent.DismissDialog) onContinue() @@ -92,7 +93,7 @@ private fun Content() { modifier = Modifier.fillMaxWidth(), items = persistentListOf( InfoListItem( - message = stringResource(CommonStrings.screen_encryption_reset_bullet_1), + message = stringResource(R.string.screen_encryption_reset_bullet_1), iconComposable = { Icon( modifier = Modifier.size(20.dp), @@ -103,7 +104,7 @@ private fun Content() { }, ), InfoListItem( - message = stringResource(CommonStrings.screen_encryption_reset_bullet_2), + message = stringResource(R.string.screen_encryption_reset_bullet_2), iconComposable = { Icon( modifier = Modifier.size(20.dp), @@ -114,7 +115,7 @@ private fun Content() { }, ), InfoListItem( - message = stringResource(CommonStrings.screen_encryption_reset_bullet_3), + message = stringResource(R.string.screen_encryption_reset_bullet_3), iconComposable = { Icon( modifier = Modifier.size(20.dp), @@ -130,7 +131,7 @@ private fun Content() { Text( modifier = Modifier.fillMaxWidth(), - text = stringResource(CommonStrings.screen_encryption_reset_footer), + text = stringResource(R.string.screen_encryption_reset_footer), style = ElementTheme.typography.fontBodyMdMedium, color = ElementTheme.colors.textActionPrimary, textAlign = TextAlign.Center, diff --git a/features/securebackup/impl/src/main/res/values/localazy.xml b/features/securebackup/impl/src/main/res/values/localazy.xml index e1159031a2..85e801fce1 100644 --- a/features/securebackup/impl/src/main/res/values/localazy.xml +++ b/features/securebackup/impl/src/main/res/values/localazy.xml @@ -16,6 +16,12 @@ "Follow the instructions to create a new recovery key" "Save your new recovery key in a password manager or encrypted note" "Reset the encryption for your account using another device" + "Your account details, contacts, preferences, and chat list will be kept" + "You will lose your existing message history" + "You will need to verify all your existing devices and contacts again" + "Only reset your identity if you don’t have access to another signed-in device and you’ve lost your recovery key." + "If you’re not signed in to any other devices and you’ve lost your recovery key, then you’ll need to reset your identity to continue using the app. " + "Reset your identity in case you can’t confirm another way" "Turn off" "You will lose your encrypted messages if you are signed out of all devices." "Are you sure you want to turn off backup?" @@ -51,4 +57,11 @@ "Make sure you can store your recovery key somewhere safe" "Recovery setup successful" "Set up recovery" + "Yes, reset now" + "This process is irreversible." + "Are you sure you want to reset your encryption?" + "An unknown error happened. Please check your account password is correct and try again." + "Enter…" + "Confirm that you want to reset your encryption." + "Enter your account password to continue" diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt index 17029452db..2449146399 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt @@ -76,12 +76,12 @@ class ResetIdentityPasswordViewTest { } @Test - fun `clicking OK dismisses the error dialog`() { + fun `modifying the password dismisses the error state`() { val eventsRecorder = EventsRecorder() rule.setResetPasswordView( ResetIdentityPasswordState(resetAction = AsyncAction.Failure(IllegalStateException("A failure")), eventSink = eventsRecorder), ) - rule.clickOn(CommonStrings.action_ok) + rule.onNodeWithText("Password").performTextInput("A password") eventsRecorder.assertSingle(ResetIdentityPasswordEvent.DismissError) } diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt index 8d14618fe8..da7f11ba42 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt @@ -20,6 +20,7 @@ import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.securebackup.impl.R import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EventsRecorder @@ -80,7 +81,7 @@ class ResetIdentityRootViewTest { ResetIdentityRootState(displayConfirmationDialog = true, eventSink = {}), onContinue = it, ) - rule.clickOn(CommonStrings.screen_reset_encryption_confirmation_alert_action) + rule.clickOn(R.string.screen_reset_encryption_confirmation_alert_action) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt index fa301e402e..82ab5e251f 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt @@ -22,13 +22,14 @@ import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle import io.element.android.libraries.matrix.api.encryption.RecoveryState +import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.simulateLongTask import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf class FakeEncryptionService( - var startIdentityResetLambda: () -> Result = { error("Not implemented") }, + var startIdentityResetLambda: () -> Result = { lambdaError() }, ) : EncryptionService { private var disableRecoveryFailure: Exception? = null override val backupStateStateFlow: MutableStateFlow = MutableStateFlow(BackupState.UNKNOWN) diff --git a/libraries/oidc/api/build.gradle.kts b/libraries/oidc/api/build.gradle.kts index 874c3ddbd4..4e01547d2c 100644 --- a/libraries/oidc/api/build.gradle.kts +++ b/libraries/oidc/api/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/libraries/oidc/impl/build.gradle.kts b/libraries/oidc/impl/build.gradle.kts index be4181e169..db1cdf8d0a 100644 --- a/libraries/oidc/impl/build.gradle.kts +++ b/libraries/oidc/impl/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,13 +43,8 @@ dependencies { implementation(projects.libraries.androidutils) implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) - implementation(projects.libraries.matrix.api) - implementation(projects.libraries.network) implementation(projects.libraries.designsystem) - implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) - implementation(projects.libraries.permissions.api) - implementation(projects.libraries.qrcode) implementation(libs.androidx.browser) implementation(platform(libs.network.retrofit.bom)) implementation(libs.network.retrofit) @@ -57,15 +52,12 @@ dependencies { api(projects.libraries.oidc.api) testImplementation(libs.test.junit) - testImplementation(libs.androidx.compose.ui.test.junit) testImplementation(libs.androidx.test.ext.junit) testImplementation(libs.coroutines.test) testImplementation(libs.molecule.runtime) - testImplementation(libs.test.robolectric) testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.permissions.test) testImplementation(projects.tests.testutils) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index ef997755dd..730afa291e 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -268,12 +268,6 @@ Reason: %1$s." "Hey, talk to me on %1$s: %2$s" "%1$s Android" "Rageshake to report bug" - "Your account details, contacts, preferences, and chat list will be kept" - "You will lose your existing message history" - "You will need to verify all your existing devices and contacts again" - "Only reset your identity if you don’t have access to another signed-in device and you’ve lost your recovery key." - "If you’re not signed in to any other devices and you’ve lost your recovery key, then you’ll need to reset your identity to continue using the app. " - "Reset your identity in case you can’t confirm another way" "Failed selecting media, please try again." "Failed processing media to upload, please try again." "Failed uploading media, please try again." @@ -284,12 +278,6 @@ Reason: %1$s." "%1$d Pinned messages" "Pinned messages" - "Yes, reset now" - "This process is irreversible." - "Are you sure you want to reset your encryption?" - "Enter…" - "Confirm that you want to reset your encryption." - "Enter your account password to continue" "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 47ef2c1c51..82fb4f2277 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -210,7 +210,10 @@ "screen_chat_backup_.*", "screen_key_backup_disable_.*", "screen_recovery_key_.*", - "screen_create_new_recovery_key_.*" + "screen_create_new_recovery_key_.*", + "screen_encryption_reset.*", + "screen_reset_encryption.*", + "screen\\.reset_encryption.*" ] }, { From faf1e7da9f597d2346796bf9a70cbccc2f9b5bb2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 14 Aug 2024 17:02:21 +0200 Subject: [PATCH 110/186] Iterate on shield mapping and rendering Also handle click on the timeline and information displayed on long click. --- .../actionlist/ActionListStateProvider.kt | 11 ++ .../impl/actionlist/ActionListView.kt | 10 +- .../messages/impl/timeline/TimelineEvents.kt | 4 + .../impl/timeline/TimelinePresenter.kt | 5 + .../messages/impl/timeline/TimelineState.kt | 3 + .../impl/timeline/TimelineStateProvider.kt | 2 + .../messages/impl/timeline/TimelineView.kt | 19 ++ .../components/ATimelineItemEventRow.kt | 1 + .../components/MessageShieldPosition.kt | 25 --- .../timeline/components/MessageShieldView.kt | 103 ++++++----- .../components/TimelineEventTimestampView.kt | 29 +++- ...melineItemEventForTimestampViewProvider.kt | 7 + .../components/TimelineItemEventRow.kt | 164 +++--------------- .../TimelineItemEventRowShieldPreview.kt | 78 +++++++++ .../TimelineItemGroupedEventsRow.kt | 7 + .../timeline/components/TimelineItemRow.kt | 4 + .../event/TimelineItemEventContentProvider.kt | 12 -- .../impl/fixtures/MessageEventFixtures.kt | 5 +- .../groups/TimelineItemGrouperTest.kt | 3 +- .../RedactedVoiceMessageManagerTest.kt | 3 +- .../components/dialogs/AlertDialog.kt | 92 ++++++++++ .../api/timeline/item/event/MessageShield.kt | 36 +++- .../item/event/EventTimelineItemMapper.kt | 22 ++- .../tests/konsist/KonsistPreviewTest.kt | 1 + 24 files changed, 400 insertions(+), 246 deletions(-) delete mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldPosition.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowShieldPreview.kt create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/AlertDialog.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt index 48c44e38c9..41c5074947 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt @@ -27,6 +27,7 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVideoContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -121,6 +122,16 @@ open class ActionListStateProvider : PreviewParameterProvider { actions = aTimelineItemPollActionList(), ), ), + anActionListState().copy( + target = ActionListState.Target.Success( + event = aTimelineItemEvent().copy( + reactionsState = reactionsState, + messageShield = MessageShield.UnknownDevice(isCritical = true) + ), + displayEmojiReactions = true, + actions = aTimelineItemActionList(), + ) + ), ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt index eb2cda8ca7..d928219fe5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt @@ -55,6 +55,7 @@ import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction +import io.element.android.features.messages.impl.timeline.components.MessageShieldView import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent @@ -181,7 +182,14 @@ private fun SheetContent( .fillMaxWidth() .padding(horizontal = 16.dp) ) - Spacer(modifier = Modifier.height(14.dp)) + if (target.event.messageShield != null) { + MessageShieldView( + shield = target.event.messageShield, + modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp) + ) + } else { + Spacer(modifier = Modifier.height(14.dp)) + } HorizontalDivider() } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt index 25ed908cd0..589ca8c6c8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt @@ -18,6 +18,7 @@ package io.element.android.features.messages.impl.timeline import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import kotlin.time.Duration sealed interface TimelineEvents { @@ -27,6 +28,9 @@ sealed interface TimelineEvents { data object OnFocusEventRender : TimelineEvents data object JumpToLive : TimelineEvents + data class ShowShieldDialog(val messageShield: MessageShield) : TimelineEvents + data object HideShieldDialog : TimelineEvents + /** * Events coming from a timeline item. */ 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 3f7db9607a..c7e3dc6e98 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 @@ -45,6 +45,7 @@ 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.roomMembers import io.element.android.libraries.matrix.api.timeline.ReceiptType +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 @@ -97,6 +98,7 @@ class TimelinePresenter @AssistedInject constructor( val prevMostRecentItemId = rememberSaveable { mutableStateOf(null) } val newEventState = remember { mutableStateOf(NewEventState.None) } + val messageShield: MutableState = remember { mutableStateOf(null) } val isSendPublicReadReceiptsEnabled by sessionPreferencesStore.isSendPublicReadReceiptsEnabled().collectAsState(initial = true) val renderReadReceipts by sessionPreferencesStore.isRenderReadReceiptsEnabled().collectAsState(initial = true) @@ -151,6 +153,8 @@ class TimelinePresenter @AssistedInject constructor( is TimelineEvents.JumpToLive -> { timelineController.focusOnLive() } + TimelineEvents.HideShieldDialog -> messageShield.value = null + is TimelineEvents.ShowShieldDialog -> messageShield.value = event.messageShield } } @@ -226,6 +230,7 @@ class TimelinePresenter @AssistedInject constructor( newEventState = newEventState.value, isLive = isLive, focusRequestState = focusRequestState.value, + messageShield = messageShield.value, eventSink = { handleEvents(it) } ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index 9339fcb620..74f8fda0b4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -20,6 +20,7 @@ import androidx.compose.runtime.Immutable import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import kotlinx.collections.immutable.ImmutableList import kotlin.time.Duration @@ -31,6 +32,8 @@ data class TimelineState( val newEventState: NewEventState, val isLive: Boolean, val focusRequestState: FocusRequestState, + // If not null, info will be rendered in a dialog + val messageShield: MessageShield?, val eventSink: (TimelineEvents) -> Unit, ) { val hasAnyEvent = timelineItems.any { it is TimelineItem.Event } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index e40a1dd78a..677989a81a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -51,6 +51,7 @@ fun aTimelineState( timelineRoomInfo: TimelineRoomInfo = aTimelineRoomInfo(), focusedEventIndex: Int = -1, isLive: Boolean = true, + messageShield: MessageShield? = null, eventSink: (TimelineEvents) -> Unit = {}, ): TimelineState { val focusedEventId = timelineItems.filterIsInstance().getOrNull(focusedEventIndex)?.eventId @@ -66,6 +67,7 @@ fun aTimelineState( newEventState = NewEventState.None, isLive = isLive, focusRequestState = focusRequestState, + messageShield = messageShield, eventSink = eventSink, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 2b62071c19..62aa351cc4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -58,6 +58,7 @@ import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.impl.timeline.components.TimelineItemRow +import io.element.android.features.messages.impl.timeline.components.toText import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.aFakeTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.focus.FocusRequestStateView @@ -68,12 +69,14 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.typing.TypingNotificationState import io.element.android.features.messages.impl.typing.TypingNotificationView import io.element.android.features.messages.impl.typing.aTypingNotificationState +import io.element.android.libraries.designsystem.components.dialogs.AlertDialog import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.FloatingActionButton import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.coroutines.launch import kotlin.math.abs @@ -124,6 +127,10 @@ fun TimelineView( state.eventSink(TimelineEvents.FocusOnEvent(eventId)) } + fun onShieldClick(shield: MessageShield) { + state.eventSink(TimelineEvents.ShowShieldDialog(shield)) + } + // Animate alpha when timeline is first displayed, to avoid flashes or glitching when viewing rooms AnimatedVisibility(visible = true, enter = fadeIn()) { Box(modifier) { @@ -154,6 +161,7 @@ fun TimelineView( focusedEventId = state.focusedEventId, onClick = onMessageClick, onLongClick = onMessageLongClick, + onShieldClick = ::onShieldClick, onUserDataClick = onUserDataClick, onLinkClick = onLinkClick, inReplyToClick = ::inReplyToClick, @@ -186,6 +194,17 @@ fun TimelineView( ) } } + + MessageShieldDialog(state) +} + +@Composable +private fun MessageShieldDialog(state: TimelineState) { + val messageShield = state.messageShield ?: return + AlertDialog( + content = messageShield.toText(), + onDismiss = { state.eventSink.invoke(TimelineEvents.HideShieldDialog) }, + ) } @Composable diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt index 8e482c020f..959b02bc4a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt @@ -37,6 +37,7 @@ internal fun ATimelineItemEventRow( isHighlighted = isHighlighted, onClick = {}, onLongClick = {}, + onShieldClick = {}, onUserDataClick = {}, onLinkClick = {}, inReplyToClick = {}, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldPosition.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldPosition.kt deleted file mode 100644 index 41c424c56e..0000000000 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldPosition.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2024 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.element.android.features.messages.impl.timeline.components - -import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield - -sealed class MessageShieldPosition { - data class InBubble(val messageShield: MessageShield) : MessageShieldPosition() - data class OutOfBubble(val messageShield: MessageShield) : MessageShieldPosition() - object None : MessageShieldPosition() -} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt index 2efa888bb7..649c03b985 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt @@ -16,19 +16,18 @@ package io.element.android.features.messages.impl.timeline.components -import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -36,52 +35,71 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.designsystem.theme.messageFromMeBackground -import io.element.android.libraries.designsystem.theme.messageFromOtherBackground import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield -import io.element.android.libraries.matrix.api.timeline.item.event.ShieldColor +import io.element.android.libraries.matrix.api.timeline.item.event.isCritical +import io.element.android.libraries.ui.strings.CommonStrings @Composable internal fun MessageShieldView( - isMine: Boolean = false, shield: MessageShield, modifier: Modifier = Modifier ) { - val borderColor = if (shield.color == ShieldColor.RED) ElementTheme.colors.borderCriticalPrimary else ElementTheme.colors.bgSubtlePrimary - val iconColor = if (shield.color == ShieldColor.RED) ElementTheme.colors.iconCriticalPrimary else ElementTheme.colors.iconSecondary - - val backgroundBubbleColor = when { - isMine -> ElementTheme.colors.messageFromMeBackground - else -> ElementTheme.colors.messageFromOtherBackground - } Row( - verticalAlignment = Alignment.Top, - modifier = modifier - .background(backgroundBubbleColor, RoundedCornerShape(8.dp)) - .border(1.dp, borderColor, RoundedCornerShape(8.dp)) - .padding(8.dp) + verticalAlignment = Alignment.CenterVertically, + modifier = modifier, ) { Icon( imageVector = shield.toIcon(), contentDescription = null, modifier = Modifier.size(15.dp), - tint = iconColor, + tint = shield.toIconColor(), ) Spacer(modifier = Modifier.size(4.dp)) - val textColor = if (shield.color == ShieldColor.RED) ElementTheme.colors.textCriticalPrimary else ElementTheme.colors.textSecondary Text( - text = shield.message, - style = ElementTheme.typography.fontBodyXsRegular, - color = textColor + text = shield.toText(), + style = ElementTheme.typography.fontBodySmMedium, + color = shield.toTextColor() ) } } @Composable -private fun MessageShield.toIcon(): ImageVector { - return when (this.color) { - ShieldColor.RED -> CompoundIcons.Error() - ShieldColor.GREY -> CompoundIcons.InfoSolid() +internal fun MessageShield.toIconColor(): Color { + return when (isCritical()) { + true -> ElementTheme.colors.iconCriticalPrimary + false -> ElementTheme.colors.iconSecondary + } +} + +@Composable +private fun MessageShield.toTextColor(): Color { + return when (isCritical()) { + true -> ElementTheme.colors.textCriticalPrimary + false -> ElementTheme.colors.textSecondary + } +} + +@Composable +internal fun MessageShield.toText(): String { + return stringResource( + id = when (this) { + is MessageShield.AuthenticityNotGuaranteed -> CommonStrings.event_shield_reason_authenticity_not_guaranteed + is MessageShield.UnknownDevice -> CommonStrings.event_shield_reason_unknown_device + is MessageShield.UnsignedDevice -> CommonStrings.event_shield_reason_unsigned_device + is MessageShield.UnverifiedIdentity -> CommonStrings.event_shield_reason_unverified_identity + is MessageShield.SentInClear -> CommonStrings.event_shield_reason_sent_in_clear + } + ) +} + +@Composable +internal fun MessageShield.toIcon(): ImageVector { + return when (this) { + is MessageShield.AuthenticityNotGuaranteed, + is MessageShield.UnverifiedIdentity -> CompoundIcons.Admin() + is MessageShield.UnknownDevice, + is MessageShield.UnsignedDevice -> CompoundIcons.HelpSolid() + is MessageShield.SentInClear -> CompoundIcons.KeyOff() } } @@ -89,31 +107,24 @@ private fun MessageShield.toIcon(): ImageVector { @Composable internal fun MessageShieldViewPreview() { ElementPreview { - Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + MessageShieldView( + shield = MessageShield.UnknownDevice(true) + ) MessageShieldView( - shield = MessageShield( - message = "The authenticity of this encrypted message can't be guaranteed on this device.", - color = ShieldColor.GREY - ) + shield = MessageShield.UnverifiedIdentity(true) ) MessageShieldView( - isMine = true, - shield = MessageShield( - message = "The authenticity of this encrypted message can't be guaranteed on this device.", - color = ShieldColor.GREY - ) + shield = MessageShield.AuthenticityNotGuaranteed(false) ) MessageShieldView( - shield = MessageShield( - message = "Encrypted by a device not verified by its owner.", - color = ShieldColor.RED - ) + shield = MessageShield.UnsignedDevice(false) ) MessageShieldView( - shield = MessageShield( - message = "Encrypted by an unknown or deleted device.", - color = ShieldColor.RED - ) + shield = MessageShield.SentInClear(false) ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt index 25181d7eb3..eb57e51006 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt @@ -16,6 +16,7 @@ package io.element.android.features.messages.impl.timeline.components +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -33,26 +34,31 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.isEdited +import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield +import io.element.android.libraries.matrix.api.timeline.item.event.isCritical import io.element.android.libraries.ui.strings.CommonStrings @Composable fun TimelineEventTimestampView( event: TimelineItem.Event, + onShieldClick: (MessageShield) -> Unit, modifier: Modifier = Modifier, ) { val formattedTime = event.sentTime val hasUnrecoverableError = event.localSendState is LocalEventSendState.SendingFailed.Unrecoverable + val hasEncryptionCritical = event.messageShield?.isCritical().orFalse() val isMessageEdited = event.content.isEdited() - val tint = if (hasUnrecoverableError) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.secondary + val tint = if (hasUnrecoverableError || hasEncryptionCritical) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.secondary Row( modifier = Modifier - .padding(PaddingValues(start = TimelineEventTimestampViewDefaults.spacing)) - .then(modifier), + .padding(PaddingValues(start = TimelineEventTimestampViewDefaults.spacing)) + .then(modifier), verticalAlignment = Alignment.CenterVertically, ) { if (isMessageEdited) { @@ -77,13 +83,28 @@ fun TimelineEventTimestampView( modifier = Modifier.size(15.dp, 18.dp), ) } + event.messageShield?.let { shield -> + Spacer(modifier = Modifier.width(2.dp)) + Icon( + imageVector = shield.toIcon(), + contentDescription = null, + modifier = Modifier + .size(15.dp) + .clickable { onShieldClick(shield) }, + tint = shield.toIconColor(), + ) + Spacer(modifier = Modifier.width(4.dp)) + } } } @PreviewsDayNight @Composable internal fun TimelineEventTimestampViewPreview(@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event) = ElementPreview { - TimelineEventTimestampView(event = event) + TimelineEventTimestampView( + event = event, + onShieldClick = {}, + ) } object TimelineEventTimestampViewDefaults { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventForTimestampViewProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventForTimestampViewProvider.kt index 84a93f1c09..705ac36df5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventForTimestampViewProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventForTimestampViewProvider.kt @@ -21,6 +21,7 @@ import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield class TimelineItemEventForTimestampViewProvider : PreviewParameterProvider { override val values: Sequence @@ -37,5 +38,11 @@ class TimelineItemEventForTimestampViewProvider : PreviewParameterProvider Unit, onLongClick: () -> Unit, + onShieldClick: (MessageShield) -> Unit, onLinkClick: (String) -> Unit, onUserDataClick: (UserId) -> Unit, inReplyToClick: (EventId) -> Unit, @@ -185,6 +182,7 @@ fun TimelineItemEventRow( interactionSource = interactionSource, onClick = onClick, onLongClick = onLongClick, + onShieldClick = onShieldClick, inReplyToClick = ::inReplyToClick, onUserDataClick = ::onUserDataClick, onReactionClick = { emoji -> onReactionClick(emoji, event) }, @@ -203,6 +201,7 @@ fun TimelineItemEventRow( interactionSource = interactionSource, onClick = onClick, onLongClick = onLongClick, + onShieldClick = onShieldClick, inReplyToClick = ::inReplyToClick, onUserDataClick = ::onUserDataClick, onReactionClick = { emoji -> onReactionClick(emoji, event) }, @@ -258,6 +257,7 @@ private fun TimelineItemEventRowContent( interactionSource: MutableInteractionSource, onClick: () -> Unit, onLongClick: () -> Unit, + onShieldClick: (MessageShield) -> Unit, inReplyToClick: () -> Unit, onUserDataClick: () -> Unit, onReactionClick: (emoji: String) -> Unit, @@ -281,7 +281,6 @@ private fun TimelineItemEventRowContent( val ( sender, message, - shield, reactions, ) = createRefs() @@ -326,6 +325,7 @@ private fun TimelineItemEventRowContent( ) { MessageEventBubbleContent( event = event, + onShieldClick = onShieldClick, onMessageLongClick = onLongClick, inReplyToClick = inReplyToClick, onLinkClick = onLinkClick, @@ -333,29 +333,6 @@ private fun TimelineItemEventRowContent( ) } - val shieldPosition = event.shieldPosition() - if (shieldPosition is MessageShieldPosition.OutOfBubble) { - MessageShieldView( - isMine = event.isMine, - shield = shieldPosition.messageShield, - modifier = Modifier - .constrainAs(shield) { - top.linkTo(message.bottom, margin = (-4).dp) - linkStartOrEnd(event) - } - .padding( - // Note: due to the applied constraints, start is left for other's message and right for mine - // In design we want a offset of 6.dp compare to the bubble, so start is 22.dp (16 + 6) - start = when { - event.isMine -> 22.dp - timelineRoomInfo.isDm -> 22.dp - else -> 22.dp + BUBBLE_INCOMING_OFFSET - }, - end = 16.dp - ), - ) - } - // Reactions if (event.reactionsState.reactions.isNotEmpty()) { TimelineItemReactionsView( @@ -367,11 +344,7 @@ private fun TimelineItemEventRowContent( onMoreReactionsClick = { onMoreReactionsClick(event) }, modifier = Modifier .constrainAs(reactions) { - if (shieldPosition is MessageShieldPosition.OutOfBubble) { - top.linkTo(shield.bottom, margin = (-4).dp) - } else { - top.linkTo(message.bottom, margin = (-4).dp) - } + top.linkTo(message.bottom, margin = (-4).dp) linkStartOrEnd(event) } .zIndex(1f) @@ -413,6 +386,7 @@ private fun MessageSenderInformation( @Composable private fun MessageEventBubbleContent( event: TimelineItem.Event, + onShieldClick: (MessageShield) -> Unit, onMessageLongClick: () -> Unit, inReplyToClick: () -> Unit, onLinkClick: (String) -> Unit, @@ -453,6 +427,7 @@ private fun MessageEventBubbleContent( @Composable fun WithTimestampLayout( timestampPosition: TimestampPosition, + onShieldClick: (MessageShield) -> Unit, modifier: Modifier = Modifier, canShrinkContent: Boolean = false, content: @Composable (onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit) -> Unit, @@ -463,6 +438,7 @@ private fun MessageEventBubbleContent( content {} TimelineEventTimestampView( event = event, + onShieldClick = onShieldClick, modifier = Modifier // Outer padding .padding(horizontal = 4.dp, vertical = 4.dp) @@ -483,6 +459,7 @@ private fun MessageEventBubbleContent( overlay = { TimelineEventTimestampView( event = event, + onShieldClick = onShieldClick, modifier = Modifier .padding(horizontal = 8.dp, vertical = 4.dp) ) @@ -493,6 +470,7 @@ private fun MessageEventBubbleContent( content {} TimelineEventTimestampView( event = event, + onShieldClick = onShieldClick, modifier = Modifier .align(Alignment.End) .padding(horizontal = 8.dp, vertical = 4.dp) @@ -505,7 +483,6 @@ private fun MessageEventBubbleContent( @Composable fun CommonLayout( timestampPosition: TimestampPosition, - messageShieldPosition: MessageShieldPosition, showThreadDecoration: Boolean, inReplyToDetails: InReplyToDetails?, modifier: Modifier = Modifier, @@ -541,35 +518,20 @@ private fun MessageEventBubbleContent( val contentWithTimestamp = @Composable { WithTimestampLayout( timestampPosition = timestampPosition, + onShieldClick = onShieldClick, canShrinkContent = canShrinkContent, modifier = timestampLayoutModifier, ) { onContentLayoutChange -> - - if (messageShieldPosition is MessageShieldPosition.InBubble) { - Column { - TimelineItemEventContentView( - content = event.content, - onLinkClick = onLinkClick, - eventSink = eventSink, - onContentLayoutChange = onContentLayoutChange, - modifier = contentModifier - ) - MessageShieldView( - modifier = Modifier.padding(start = 8.dp, end = 8.dp), - shield = messageShieldPosition.messageShield, - ) - } - } else { - TimelineItemEventContentView( - content = event.content, - onLinkClick = onLinkClick, - eventSink = eventSink, - onContentLayoutChange = onContentLayoutChange, - modifier = contentModifier - ) - } + TimelineItemEventContentView( + content = event.content, + onLinkClick = onLinkClick, + eventSink = eventSink, + onContentLayoutChange = onContentLayoutChange, + modifier = contentModifier + ) } } + val inReplyTo = @Composable { inReplyTo: InReplyToDetails -> val topPadding = if (showThreadDecoration) 0.dp else 8.dp val inReplyToModifier = Modifier @@ -602,11 +564,9 @@ private fun MessageEventBubbleContent( is TimelineItemPollContent -> TimestampPosition.Below else -> TimestampPosition.Default } - val messageShieldPosition = event.shieldPosition() CommonLayout( showThreadDecoration = event.isThreaded, - messageShieldPosition = messageShieldPosition, - timestampPosition = if (messageShieldPosition is MessageShieldPosition.InBubble) TimestampPosition.Below else timestampPosition, + timestampPosition = timestampPosition, inReplyToDetails = event.inReplyTo, canShrinkContent = event.content is TimelineItemVoiceContent, modifier = bubbleModifier.semantics(mergeDescendants = true) { @@ -643,83 +603,3 @@ internal fun TimelineItemEventRowPreview() = ElementPreview { } } } - -@Preview( - name = "Encryption Shields" -) -@Preview( - name = "Encryption Shields - Night", - uiMode = Configuration.UI_MODE_NIGHT_YES -) -@Composable -internal fun TimelineItemEventRowShieldsPreview() = ElementPreview { - Column { - ATimelineItemEventRow( - event = aTimelineItemEvent( - senderDisplayName = "Sender with a super long name that should ellipsize", - isMine = true, - content = aTimelineItemTextContent( - body = "Message sent from unsigned device" - ), - groupPosition = TimelineItemGroupPosition.First, - messageShield = aRedShield() - ), - ) - ATimelineItemEventRow( - event = aTimelineItemEvent( - senderDisplayName = "Sender with a super long name that should ellipsize", - content = aTimelineItemTextContent( - body = "Short Message with authenticity warning" - ), - groupPosition = TimelineItemGroupPosition.Middle, - messageShield = aGreyShield() - ), - ) - ATimelineItemEventRow( - event = aTimelineItemEvent( - isMine = true, - content = aTimelineItemImageContent().copy( - aspectRatio = 2.5f - ), - groupPosition = TimelineItemGroupPosition.Last, - messageShield = aRedShield() - ), - ) - ATimelineItemEventRow( - event = aTimelineItemEvent( - content = aTimelineItemImageContent().copy( - aspectRatio = 2.5f - ), - groupPosition = TimelineItemGroupPosition.Last, - messageShield = aGreyShield() - ), - ) - } -} - -@Composable -@ReadOnlyComposable -private fun TimelineItem.Event.shieldPosition(): MessageShieldPosition { - val shield = this.messageShield ?: return MessageShieldPosition.None - - // sdk returns raw human readable strings, add i18n support - val localizedMessage = when (shield.message) { - "The authenticity of this encrypted message can't be guaranteed on this device." -> stringResource( - CommonStrings.event_shield_reason_authenticity_not_guaranteed - ) - "Encrypted by a device not verified by its owner." -> stringResource(CommonStrings.event_shield_reason_unsigned_device) - "Encrypted by an unknown or deleted device." -> stringResource(CommonStrings.event_shield_reason_unknown_device) - "Encrypted by an unverified user." -> stringResource(CommonStrings.event_shield_reason_unverified_identity) - else -> shield.message - } - val localShield = shield.copy(message = localizedMessage) - - return when (this.content) { - is TimelineItemImageContent, - is TimelineItemVideoContent, - is TimelineItemStickerContent, - is TimelineItemLocationContent, - is TimelineItemPollContent -> MessageShieldPosition.OutOfBubble(localShield) - else -> MessageShieldPosition.InBubble(localShield) - } -} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowShieldPreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowShieldPreview.kt new file mode 100644 index 0000000000..00be5d692c --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowShieldPreview.kt @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.timeline.components + +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import io.element.android.features.messages.impl.timeline.aTimelineItemEvent +import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield + +@PreviewsDayNight +@Composable +internal fun TimelineItemEventRowShieldPreview() = ElementPreview { + Column { + ATimelineItemEventRow( + event = aTimelineItemEvent( + senderDisplayName = "Sender with a super long name that should ellipsize", + isMine = true, + content = aTimelineItemTextContent( + body = "Message sent from unsigned device" + ), + groupPosition = TimelineItemGroupPosition.First, + messageShield = aCriticalShield() + ), + ) + ATimelineItemEventRow( + event = aTimelineItemEvent( + senderDisplayName = "Sender with a super long name that should ellipsize", + content = aTimelineItemTextContent( + body = "Short Message with authenticity warning" + ), + groupPosition = TimelineItemGroupPosition.Middle, + messageShield = aWarningShield() + ), + ) + ATimelineItemEventRow( + event = aTimelineItemEvent( + isMine = true, + content = aTimelineItemImageContent().copy( + aspectRatio = 2.5f + ), + groupPosition = TimelineItemGroupPosition.Last, + messageShield = aCriticalShield() + ), + ) + ATimelineItemEventRow( + event = aTimelineItemEvent( + content = aTimelineItemImageContent().copy( + aspectRatio = 2.5f + ), + groupPosition = TimelineItemGroupPosition.Last, + messageShield = aWarningShield() + ), + ) + } +} + +private fun aWarningShield() = MessageShield.AuthenticityNotGuaranteed(isCritical = false) + +private fun aCriticalShield() = MessageShield.UnverifiedIdentity(isCritical = true) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt index 4dd4d4e356..bb1cb2b2df 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt @@ -36,6 +36,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield @Composable fun TimelineItemGroupedEventsRow( @@ -46,6 +47,7 @@ fun TimelineItemGroupedEventsRow( focusedEventId: EventId?, onClick: (TimelineItem.Event) -> Unit, onLongClick: (TimelineItem.Event) -> Unit, + onShieldClick: (MessageShield) -> Unit, inReplyToClick: (EventId) -> Unit, onUserDataClick: (UserId) -> Unit, onLinkClick: (String) -> Unit, @@ -72,6 +74,7 @@ fun TimelineItemGroupedEventsRow( isLastOutgoingMessage = isLastOutgoingMessage, onClick = onClick, onLongClick = onLongClick, + onShieldClick = onShieldClick, inReplyToClick = inReplyToClick, onUserDataClick = onUserDataClick, onLinkClick = onLinkClick, @@ -95,6 +98,7 @@ private fun TimelineItemGroupedEventsRowContent( isLastOutgoingMessage: Boolean, onClick: (TimelineItem.Event) -> Unit, onLongClick: (TimelineItem.Event) -> Unit, + onShieldClick: (MessageShield) -> Unit, inReplyToClick: (EventId) -> Unit, onUserDataClick: (UserId) -> Unit, onLinkClick: (String) -> Unit, @@ -127,6 +131,7 @@ private fun TimelineItemGroupedEventsRowContent( focusedEventId = focusedEventId, onClick = onClick, onLongClick = onLongClick, + onShieldClick = onShieldClick, inReplyToClick = inReplyToClick, onUserDataClick = onUserDataClick, onLinkClick = onLinkClick, @@ -168,6 +173,7 @@ internal fun TimelineItemGroupedEventsRowContentExpandedPreview() = ElementPrevi isLastOutgoingMessage = false, onClick = {}, onLongClick = {}, + onShieldClick = {}, inReplyToClick = {}, onUserDataClick = {}, onLinkClick = {}, @@ -192,6 +198,7 @@ internal fun TimelineItemGroupedEventsRowContentCollapsePreview() = ElementPrevi isLastOutgoingMessage = false, onClick = {}, onLongClick = {}, + onShieldClick = {}, inReplyToClick = {}, onUserDataClick = {}, onLinkClick = {}, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index 2a3a0305c2..9cbcf20bef 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -37,6 +37,7 @@ import io.element.android.libraries.designsystem.text.toPx import io.element.android.libraries.designsystem.theme.highlightedMessageBackgroundColor import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield @Composable internal fun TimelineItemRow( @@ -49,6 +50,7 @@ internal fun TimelineItemRow( onLinkClick: (String) -> Unit, onClick: (TimelineItem.Event) -> Unit, onLongClick: (TimelineItem.Event) -> Unit, + onShieldClick: (MessageShield) -> Unit, inReplyToClick: (EventId) -> Unit, onReactionClick: (key: String, TimelineItem.Event) -> Unit, onReactionLongClick: (key: String, TimelineItem.Event) -> Unit, @@ -110,6 +112,7 @@ internal fun TimelineItemRow( isHighlighted = timelineItem.isEvent(focusedEventId), onClick = { onClick(timelineItem) }, onLongClick = { onLongClick(timelineItem) }, + onShieldClick = onShieldClick, onUserDataClick = onUserDataClick, onLinkClick = onLinkClick, inReplyToClick = inReplyToClick, @@ -132,6 +135,7 @@ internal fun TimelineItemRow( focusedEventId = focusedEventId, onClick = onClick, onLongClick = onLongClick, + onShieldClick = onShieldClick, inReplyToClick = inReplyToClick, onUserDataClick = onUserDataClick, onLinkClick = onLinkClick, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt index e103c44d1c..29fa048e1f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt @@ -21,8 +21,6 @@ import android.text.style.StyleSpan import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.core.text.buildSpannedString import androidx.core.text.inSpans -import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield -import io.element.android.libraries.matrix.api.timeline.item.event.ShieldColor import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent class TimelineItemEventContentProvider : PreviewParameterProvider { @@ -104,13 +102,3 @@ fun aTimelineItemStateEventContent( ) = TimelineItemStateEventContent( body = body, ) - -fun aGreyShield() = MessageShield( - message = "The authenticity of this encrypted message can't be guaranteed on this device.", - color = ShieldColor.GREY -) - -fun aRedShield() = MessageShield( - message = "Encrypted by a device not verified by its owner.", - color = ShieldColor.RED -) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt index ca805d44c7..c712421f23 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt @@ -29,6 +29,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_MESSAGE import io.element.android.libraries.matrix.test.A_USER_ID @@ -48,6 +49,7 @@ internal fun aMessageEvent( isThreaded: Boolean = false, debugInfo: TimelineItemDebugInfo = aTimelineItemDebugInfo(), sendState: LocalEventSendState = LocalEventSendState.Sent(AN_EVENT_ID), + messageShield: MessageShield? = null, ) = TimelineItem.Event( id = eventId?.value.orEmpty(), eventId = eventId, @@ -66,5 +68,6 @@ internal fun aMessageEvent( inReplyTo = inReplyTo, debugInfo = debugInfo, isThreaded = isThreaded, - origin = null + origin = null, + messageShield = messageShield, ) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt index e044ac7e2b..fc98b34feb 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt @@ -50,7 +50,8 @@ class TimelineItemGrouperTest { inReplyTo = null, isThreaded = false, debugInfo = aTimelineItemDebugInfo(), - origin = null + origin = null, + messageShield = null, ) private val aNonGroupableItem = aMessageEvent() private val aNonGroupableItemNoEvent = TimelineItem.Virtual("virtual", aTimelineItemDaySeparatorModel("Today")) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt index 2a54edad58..93882d5f3e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt @@ -101,7 +101,8 @@ fun aRedactedMatrixTimeline(eventId: EventId) = listOf( originalJson = null, latestEditedJson = null ), - origin = null + origin = null, + messageShield = null, ), ) ) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/AlertDialog.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/AlertDialog.kt new file mode 100644 index 0000000000..f22a573e77 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/AlertDialog.kt @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.components.dialogs + +import androidx.compose.material3.BasicAlertDialog +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.ElementThemedPreview +import io.element.android.libraries.designsystem.preview.PreviewGroup +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.DialogPreview +import io.element.android.libraries.designsystem.theme.components.SimpleAlertDialogContent +import io.element.android.libraries.ui.strings.CommonStrings + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AlertDialog( + content: String, + onDismiss: () -> Unit, + modifier: Modifier = Modifier, + title: String? = null, + submitText: String = AlertDialogDefaults.submitText, +) { + BasicAlertDialog(modifier = modifier, onDismissRequest = onDismiss) { + AlertDialogContent( + title = title, + content = content, + submitText = submitText, + onSubmitClick = onDismiss, + ) + } +} + +@Composable +private fun AlertDialogContent( + content: String, + onSubmitClick: () -> Unit, + title: String? = AlertDialogDefaults.title, + submitText: String = AlertDialogDefaults.submitText, +) { + SimpleAlertDialogContent( + title = title, + content = content, + submitText = submitText, + onSubmitClick = onSubmitClick, + ) +} + +object AlertDialogDefaults { + val title: String? @Composable get() = null + val submitText: String @Composable get() = stringResource(id = CommonStrings.action_ok) +} + +@Preview(group = PreviewGroup.Dialogs) +@Composable +internal fun AlertDialogContentPreview() { + ElementThemedPreview(showBackground = false) { + DialogPreview { + AlertDialogContent( + content = "Content", + onSubmitClick = {}, + ) + } + } +} + +@PreviewsDayNight +@Composable +internal fun AlertDialogPreview() = ElementPreview { + AlertDialog( + content = "Content", + onDismiss = {}, + ) +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt index 58fc96d8b1..7323f9b712 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt @@ -16,12 +16,32 @@ package io.element.android.libraries.matrix.api.timeline.item.event -data class MessageShield( - val message: String, - val color: ShieldColor, -) - -enum class ShieldColor { - RED, - GREY +import androidx.compose.runtime.Immutable + +@Immutable +sealed interface MessageShield { + /** Not enough information available to check the authenticity.*/ + data class AuthenticityNotGuaranteed(val isCritical: Boolean) : MessageShield + + /** The sending device isn't yet known by the Client.*/ + data class UnknownDevice(val isCritical: Boolean) : MessageShield + + /** The sending device hasn't been verified by the sender.*/ + data class UnsignedDevice(val isCritical: Boolean) : MessageShield + + /** The sender hasn't been verified by the Client's user.*/ + data class UnverifiedIdentity(val isCritical: Boolean) : MessageShield + + /** An unencrypted event in an encrypted room.*/ + data class SentInClear(val isCritical: Boolean) : MessageShield +} + +fun MessageShield.isCritical(): Boolean { + return when (this) { + is MessageShield.AuthenticityNotGuaranteed -> isCritical + is MessageShield.UnknownDevice -> isCritical + is MessageShield.UnsignedDevice -> isCritical + is MessageShield.UnverifiedIdentity -> isCritical + is MessageShield.SentInClear -> isCritical + } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt index 1c5f25a14e..523b8e1fb5 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt @@ -27,13 +27,13 @@ import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails import io.element.android.libraries.matrix.api.timeline.item.event.ReactionSender import io.element.android.libraries.matrix.api.timeline.item.event.Receipt -import io.element.android.libraries.matrix.api.timeline.item.event.ShieldColor import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import org.matrix.rustcomponents.sdk.Reaction import org.matrix.rustcomponents.sdk.ShieldState +import uniffi.matrix_sdk_common.ShieldStateCode import org.matrix.rustcomponents.sdk.EventSendState as RustEventSendState import org.matrix.rustcomponents.sdk.EventTimelineItem as RustEventTimelineItem import org.matrix.rustcomponents.sdk.EventTimelineItemDebugInfo as RustEventTimelineItemDebugInfo @@ -135,10 +135,22 @@ private fun RustEventItemOrigin.map(): TimelineItemEventOrigin { } private fun ShieldState?.map(): MessageShield? { - return when (this) { - is ShieldState.Grey -> MessageShield(message = this.message, color = ShieldColor.GREY) - is ShieldState.Red -> MessageShield(message = this.message, color = ShieldColor.RED) + this ?: return null + val shieldStateCode = when (this) { + is ShieldState.Grey -> code + is ShieldState.Red -> code + ShieldState.None -> null + } ?: return null + val isCritical = when (this) { ShieldState.None, - null -> null + is ShieldState.Grey -> false + is ShieldState.Red -> true + } + return when (shieldStateCode) { + ShieldStateCode.AUTHENTICITY_NOT_GUARANTEED -> MessageShield.AuthenticityNotGuaranteed(isCritical) + ShieldStateCode.UNKNOWN_DEVICE -> MessageShield.UnknownDevice(isCritical) + ShieldStateCode.UNSIGNED_DEVICE -> MessageShield.UnsignedDevice(isCritical) + ShieldStateCode.UNVERIFIED_IDENTITY -> MessageShield.UnverifiedIdentity(isCritical) + ShieldStateCode.SENT_IN_CLEAR -> MessageShield.SentInClear(isCritical) } } 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 ccf6754fc5..3fb609b0b5 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 @@ -120,6 +120,7 @@ class KonsistPreviewTest { "TextComposerVoicePreview", "TimelineImageWithCaptionRowPreview", "TimelineItemEventRowForDirectRoomPreview", + "TimelineItemEventRowShieldPreview", "TimelineItemEventRowTimestampPreview", "TimelineItemEventRowWithManyReactionsPreview", "TimelineItemEventRowWithRRPreview", From 99efdb6d76394a727ada7473264c45d08129be26 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 14 Aug 2024 15:31:44 +0000 Subject: [PATCH 111/186] Update screenshots --- ...impl.reset.password_ResetIdentityPasswordView_Day_0_en.png | 4 ++-- ...impl.reset.password_ResetIdentityPasswordView_Day_1_en.png | 3 +++ ...impl.reset.password_ResetIdentityPasswordView_Day_2_en.png | 3 +++ ...impl.reset.password_ResetIdentityPasswordView_Day_3_en.png | 3 +++ ...pl.reset.password_ResetIdentityPasswordView_Night_0_en.png | 4 ++-- ...pl.reset.password_ResetIdentityPasswordView_Night_1_en.png | 3 +++ ...pl.reset.password_ResetIdentityPasswordView_Night_2_en.png | 3 +++ ...pl.reset.password_ResetIdentityPasswordView_Night_3_en.png | 3 +++ 8 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png index e82254087f..a49af920d9 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:688c50e8f414a6bdb3dd0e718f8de426badcea744509069a3023dfc2d2e59816 -size 29040 +oid sha256:e09769c04ba21aba09eb0de5865f659ad092ba2e46a8b3933f95b1170b09d303 +size 28540 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png new file mode 100644 index 0000000000..4c6ae5f149 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3702ebe296d7a14e20b3d683fb79f6b2455064a8986ce48c870b5cfd68dc5933 +size 27407 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png new file mode 100644 index 0000000000..4c6ae5f149 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3702ebe296d7a14e20b3d683fb79f6b2455064a8986ce48c870b5cfd68dc5933 +size 27407 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png new file mode 100644 index 0000000000..1d5e048087 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b683ed9986e3fd139ee735e51a369322ba3652b2b8a578c05a61f26ee27898e0 +size 39996 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png index 9b905f24c2..96ec36ca5e 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:061cebcf9a9646fb6c962272692fa123d60b9e17cd6b29b581c17ef125880a9e -size 28166 +oid sha256:14d4ed02bb2f949c4cbba84933bbbfb0c550ad261695a371ef12e74a2dbd8812 +size 27600 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png new file mode 100644 index 0000000000..c4e2dae54b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53f3dc9352250ba7495b6af312f3f370463291d29b76c40d4b3c340b77aa5712 +size 25455 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png new file mode 100644 index 0000000000..c4e2dae54b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53f3dc9352250ba7495b6af312f3f370463291d29b76c40d4b3c340b77aa5712 +size 25455 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png new file mode 100644 index 0000000000..0fa0e6a519 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b380335d847fa37e5319541f46f341c5fe8016f3af48765cfe7537c59dd1f58a +size 38379 From 0661cd20467d3e1475520f5296842768cc7e143f Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 14 Aug 2024 15:49:23 +0000 Subject: [PATCH 112/186] Update screenshots --- ...eatures.messages.impl.actionlist_SheetContent_Day_11_en.png | 3 +++ ...tures.messages.impl.actionlist_SheetContent_Night_11_en.png | 3 +++ ...ges.impl.timeline.components_MessageShieldView_Day_0_en.png | 3 +++ ...s.impl.timeline.components_MessageShieldView_Night_0_en.png | 3 +++ ...timeline.components_TimelineEventTimestampView_Day_5_en.png | 3 +++ ...timeline.components_TimelineEventTimestampView_Day_6_en.png | 3 +++ ...meline.components_TimelineEventTimestampView_Night_5_en.png | 3 +++ ...meline.components_TimelineEventTimestampView_Night_6_en.png | 3 +++ ...timeline.components_TimelineItemEventRowShield_Day_0_en.png | 3 +++ ...meline.components_TimelineItemEventRowShield_Night_0_en.png | 3 +++ ...eline.components_TimelineItemEventRowTimestamp_Day_5_en.png | 3 +++ ...eline.components_TimelineItemEventRowTimestamp_Day_6_en.png | 3 +++ ...ine.components_TimelineItemEventRowTimestamp_Night_5_en.png | 3 +++ ...ine.components_TimelineItemEventRowTimestamp_Night_6_en.png | 3 +++ ...system.components.dialogs_AlertDialogContent_Dialogs_en.png | 3 +++ ...es.designsystem.components.dialogs_AlertDialog_Day_0_en.png | 3 +++ ....designsystem.components.dialogs_AlertDialog_Night_0_en.png | 3 +++ 17 files changed, 51 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_11_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_11_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialog_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialog_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_11_en.png new file mode 100644 index 0000000000..2a383f511b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dfd9526209bdb36863765802036b08a4a61ae8035afed4f47b262d521d8bd37d +size 45145 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_11_en.png new file mode 100644 index 0000000000..2d2c2ad36d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b82542b62c8a35c59f96c1b348a62f71de0d1302550458f11581ddec65b2172 +size 44342 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png new file mode 100644 index 0000000000..626e88bcc1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c6c05a05fa51e513937162578540f720e138e5263213211b51c0af54c295c6d0 +size 30756 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png new file mode 100644 index 0000000000..27073d532c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:679652bc8587d10595565c55ac633c84b5650c9cf4a513e03be5de0cb2eaa012 +size 29933 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en.png new file mode 100644 index 0000000000..c477c15bb5 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ba7b49b4872d05bb5a277024a8c0786dd7a8b8c3db6462a455cbd73e682602a +size 4910 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en.png new file mode 100644 index 0000000000..3585275158 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f45afae6e96d3cddb50eda9acac94ba7b556e480eccf56e5f7c4c17a7a5bfb7 +size 5009 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en.png new file mode 100644 index 0000000000..efa2ef9520 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1597f66fc8a4054b2dbca912c4cf2d2088692cc727f5b1ecfa0b82f3c3d71bf0 +size 4845 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en.png new file mode 100644 index 0000000000..d5a4f8dde6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e07f82770e48bcd04bf5532dd353d0f84d6128911e692a8e728f1b768d0b947 +size 4988 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png new file mode 100644 index 0000000000..e2cbde040e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87dfe8aa9c89ac21b273eabc4f92e12681d114daa408fc999bba5b209b47f9d8 +size 148921 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png new file mode 100644 index 0000000000..771599f98d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89ef14c0376205fa40582bbb882180aacb8729025e65b02c2231fc848d807911 +size 148430 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en.png new file mode 100644 index 0000000000..4050bdcab5 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:196ec6c84cc1c975091f8455fdbce2fdf928243c888ee6eeaf32127736686f85 +size 30369 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_6_en.png new file mode 100644 index 0000000000..9a163d48b2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1381e2fd76dbb52a67fb12d588c839b92a5701c2abf3d2fc14d89fead977a35e +size 30727 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en.png new file mode 100644 index 0000000000..0699e39d83 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b266883f18631845e979bdc9f3bc6d375891f5e37d6839873486f367a0a43dc1 +size 30712 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_6_en.png new file mode 100644 index 0000000000..28cb3b58b8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07036aaecb01e2b27e133a2d9f254ef38ff8ab18913a2684db1391aa829bd3ed +size 30945 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en.png new file mode 100644 index 0000000000..6bc3482fa9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be622097026463273020202508a7990f358b5eb33103917be2bc272e744d7a76 +size 11310 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialog_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialog_Day_0_en.png new file mode 100644 index 0000000000..6ef9f48c82 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialog_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c01359ad5875334bc4904a3cfb171f8d4cc87e6452591a72435c8b3f116439ac +size 8398 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialog_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialog_Night_0_en.png new file mode 100644 index 0000000000..0a326effa4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_AlertDialog_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e47308ddbd1310aadf5471dbe7c1ba3d22e26555d3f08514ea13b4acc3cf07b8 +size 7048 From e4adb15778676ea9a4695b9a900c96d13fa66f1c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 00:44:35 +0000 Subject: [PATCH 113/186] Update dependency androidx.test:runner to v1.6.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 5afd73b9ce..9b613e0ebf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -138,7 +138,7 @@ test_core = { module = "androidx.test:core", version.ref = "test_core" } 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.6.1" +test_runner = "androidx.test:runner:1.6.2" test_mockk = "io.mockk:mockk:1.13.12" test_konsist = "com.lemonappdev:konsist:0.15.1" test_turbine = "app.cash.turbine:turbine:1.1.0" From 8b81690903792e8ad053a39abe2ce52bd01b22a2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:37:57 +0000 Subject: [PATCH 114/186] Update dependency com.otaliastudios:transcoder to v0.11.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 5afd73b9ce..731c96bcaa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -172,7 +172,7 @@ sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", sqlcipher = "net.zetetic:android-database-sqlcipher:4.5.4" sqlite = "androidx.sqlite:sqlite-ktx:2.4.0" unifiedpush = "com.github.UnifiedPush:android-connector:2.4.0" -otaliastudios_transcoder = "com.otaliastudios:transcoder:0.10.5" +otaliastudios_transcoder = "com.otaliastudios:transcoder:0.11.0" 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" } From 3676bca042746dab943d2ab8f345b7e4951b972d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Aug 2024 09:18:13 +0200 Subject: [PATCH 115/186] Make extension isCritical a val instead of a fun. --- .../impl/timeline/components/MessageShieldView.kt | 4 ++-- .../components/TimelineEventTimestampView.kt | 2 +- .../api/timeline/item/event/MessageShield.kt | 15 +++++++-------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt index 649c03b985..4b1415e8d4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt @@ -65,7 +65,7 @@ internal fun MessageShieldView( @Composable internal fun MessageShield.toIconColor(): Color { - return when (isCritical()) { + return when (isCritical) { true -> ElementTheme.colors.iconCriticalPrimary false -> ElementTheme.colors.iconSecondary } @@ -73,7 +73,7 @@ internal fun MessageShield.toIconColor(): Color { @Composable private fun MessageShield.toTextColor(): Color { - return when (isCritical()) { + return when (isCritical) { true -> ElementTheme.colors.textCriticalPrimary false -> ElementTheme.colors.textSecondary } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt index eb57e51006..a7500531b2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt @@ -52,7 +52,7 @@ fun TimelineEventTimestampView( ) { val formattedTime = event.sentTime val hasUnrecoverableError = event.localSendState is LocalEventSendState.SendingFailed.Unrecoverable - val hasEncryptionCritical = event.messageShield?.isCritical().orFalse() + val hasEncryptionCritical = event.messageShield?.isCritical.orFalse() val isMessageEdited = event.content.isEdited() val tint = if (hasUnrecoverableError || hasEncryptionCritical) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.secondary Row( diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt index 7323f9b712..9092817569 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt @@ -20,28 +20,27 @@ import androidx.compose.runtime.Immutable @Immutable sealed interface MessageShield { - /** Not enough information available to check the authenticity.*/ + /** Not enough information available to check the authenticity. */ data class AuthenticityNotGuaranteed(val isCritical: Boolean) : MessageShield - /** The sending device isn't yet known by the Client.*/ + /** The sending device isn't yet known by the Client. */ data class UnknownDevice(val isCritical: Boolean) : MessageShield - /** The sending device hasn't been verified by the sender.*/ + /** The sending device hasn't been verified by the sender. */ data class UnsignedDevice(val isCritical: Boolean) : MessageShield - /** The sender hasn't been verified by the Client's user.*/ + /** The sender hasn't been verified by the Client's user. */ data class UnverifiedIdentity(val isCritical: Boolean) : MessageShield - /** An unencrypted event in an encrypted room.*/ + /** An unencrypted event in an encrypted room. */ data class SentInClear(val isCritical: Boolean) : MessageShield } -fun MessageShield.isCritical(): Boolean { - return when (this) { +val MessageShield.isCritical: Boolean + get() = when (this) { is MessageShield.AuthenticityNotGuaranteed -> isCritical is MessageShield.UnknownDevice -> isCritical is MessageShield.UnsignedDevice -> isCritical is MessageShield.UnverifiedIdentity -> isCritical is MessageShield.SentInClear -> isCritical } -} From 4efa95bc0b64f1c16bdb492d3c591cac289bf362 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Aug 2024 09:27:19 +0200 Subject: [PATCH 116/186] Iterate on mapping MessageShield -> icon iOS impl: https://github.com/element-hq/element-x-ios/blob/develop/ElementX/Sources/Services/Timeline/TimelineItemContent/EncryptionAuthenticity.swift#L59-L65 --- .../impl/timeline/components/MessageShieldView.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt index 4b1415e8d4..73d4c9ba88 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt @@ -95,11 +95,11 @@ internal fun MessageShield.toText(): String { @Composable internal fun MessageShield.toIcon(): ImageVector { return when (this) { - is MessageShield.AuthenticityNotGuaranteed, - is MessageShield.UnverifiedIdentity -> CompoundIcons.Admin() + is MessageShield.AuthenticityNotGuaranteed -> CompoundIcons.Info() is MessageShield.UnknownDevice, - is MessageShield.UnsignedDevice -> CompoundIcons.HelpSolid() - is MessageShield.SentInClear -> CompoundIcons.KeyOff() + is MessageShield.UnsignedDevice, + is MessageShield.UnverifiedIdentity -> CompoundIcons.HelpSolid() + is MessageShield.SentInClear -> CompoundIcons.LockOff() } } From ced4f0c0180f8469e0a5c2164d7f300048141328 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 16 Aug 2024 08:07:11 +0000 Subject: [PATCH 117/186] Update screenshots --- ...es.impl.timeline.components_MessageShieldView_Day_0_en.png | 4 ++-- ....impl.timeline.components_MessageShieldView_Night_0_en.png | 4 ++-- ...imeline.components_TimelineEventTimestampView_Day_5_en.png | 4 ++-- ...eline.components_TimelineEventTimestampView_Night_5_en.png | 4 ++-- ...imeline.components_TimelineItemEventRowShield_Day_0_en.png | 4 ++-- ...eline.components_TimelineItemEventRowShield_Night_0_en.png | 4 ++-- ...line.components_TimelineItemEventRowTimestamp_Day_5_en.png | 4 ++-- ...ne.components_TimelineItemEventRowTimestamp_Night_5_en.png | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png index 626e88bcc1..aa89a718dc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6c05a05fa51e513937162578540f720e138e5263213211b51c0af54c295c6d0 -size 30756 +oid sha256:18808ed71ef0cbc10be0eda977ab077a0eaa83afbfd2ae50c500b802aa4c7976 +size 30901 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png index 27073d532c..9b49043ac6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:679652bc8587d10595565c55ac633c84b5650c9cf4a513e03be5de0cb2eaa012 -size 29933 +oid sha256:1d0ad0c7f690d07d67a13fcad3ee8901a77602affe063d2f8222345de3aff934 +size 30039 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en.png index c477c15bb5..b0b3fd1a0b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ba7b49b4872d05bb5a277024a8c0786dd7a8b8c3db6462a455cbd73e682602a -size 4910 +oid sha256:6d37081422eb655aaaa58834912625efd07f61eddcb7117f32b8edb9512969ab +size 5052 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en.png index efa2ef9520..8759060547 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1597f66fc8a4054b2dbca912c4cf2d2088692cc727f5b1ecfa0b82f3c3d71bf0 -size 4845 +oid sha256:6dcce84695624b516035b2a3fe33ad71bf0b278a769ac013ad7c9b4feae958c5 +size 5028 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png index e2cbde040e..0186b92f5f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87dfe8aa9c89ac21b273eabc4f92e12681d114daa408fc999bba5b209b47f9d8 -size 148921 +oid sha256:c4ba97a7a22e790d2708364c32035d8428677deaa12ff62c0304d252a1043f7a +size 149223 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png index 771599f98d..6660328620 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:89ef14c0376205fa40582bbb882180aacb8729025e65b02c2231fc848d807911 -size 148430 +oid sha256:007de1b45bde33d6a7a8ea389a1b80a07f0696878ecfe34cbcf12c74b866ed09 +size 148817 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en.png index 4050bdcab5..e78b401753 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:196ec6c84cc1c975091f8455fdbce2fdf928243c888ee6eeaf32127736686f85 -size 30369 +oid sha256:99acfb92911fbc7b60126cdadbd5b373f9692258d4f6c59a8167425e7b5603b5 +size 30870 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en.png index 0699e39d83..ce1c266e0a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b266883f18631845e979bdc9f3bc6d375891f5e37d6839873486f367a0a43dc1 -size 30712 +oid sha256:7348bb4cc9cde7eda1c7f65ce5f997838add5d8a84974b13bcf6685b15c80f1a +size 31136 From 3f90b02e5497e627efc5dc45cbb4166480997fb5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Aug 2024 10:45:20 +0200 Subject: [PATCH 118/186] Add test on `TimelineEvents.ShowShieldDialog` and `TimelineEvents.HideShieldDialog` --- .../TimelineItemEventRowShieldPreview.kt | 2 +- .../impl/timeline/TimelinePresenterTest.kt | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowShieldPreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowShieldPreview.kt index 00be5d692c..828060fd1f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowShieldPreview.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowShieldPreview.kt @@ -75,4 +75,4 @@ internal fun TimelineItemEventRowShieldPreview() = ElementPreview { private fun aWarningShield() = MessageShield.AuthenticityNotGuaranteed(isCritical = false) -private fun aCriticalShield() = MessageShield.UnverifiedIdentity(isCritical = true) +internal fun aCriticalShield() = MessageShield.UnverifiedIdentity(isCritical = true) 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 90c71a964a..a155507817 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 @@ -24,6 +24,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.FakeMessagesNavigator import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactory +import io.element.android.features.messages.impl.timeline.components.aCriticalShield import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem @@ -591,6 +592,26 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" } } + @Test + fun `present - show shield hide shield`() = runTest { + val presenter = createTimelinePresenter() + val shield = aCriticalShield() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitFirstItem() + assertThat(initialState.messageShield).isNull() + initialState.eventSink(TimelineEvents.ShowShieldDialog(shield)) + awaitItem().also { state -> + assertThat(state.messageShield).isEqualTo(shield) + state.eventSink(TimelineEvents.HideShieldDialog) + } + awaitItem().also { state -> + assertThat(state.messageShield).isNull() + } + } + } + @Test fun `present - when room member info is loaded, read receipts info should be updated`() = runTest { val timeline = FakeTimeline( From 2116108a2c83e09f6cfcbda080df65da0774bd92 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Aug 2024 11:14:51 +0200 Subject: [PATCH 119/186] Add UI test on clicking on message shield. Need to add content description on the shield icon. --- .../components/TimelineEventTimestampView.kt | 2 +- .../impl/timeline/TimelineViewTest.kt | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt index a7500531b2..69c2a807a2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt @@ -87,7 +87,7 @@ fun TimelineEventTimestampView( Spacer(modifier = Modifier.width(2.dp)) Icon( imageVector = shield.toIcon(), - contentDescription = null, + contentDescription = shield.toText(), modifier = Modifier .size(15.dp) .clickable { onShieldClick(shield) }, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt index e66bd4c7a1..bb8ea58315 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt @@ -22,17 +22,21 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.performClick import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.messages.impl.timeline.components.aCriticalShield import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemLoadingIndicatorModel import io.element.android.features.messages.impl.typing.TypingNotificationState import io.element.android.features.messages.impl.typing.aTypingNotificationState import io.element.android.libraries.matrix.api.core.UserId 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.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EnsureNeverCalledWithParam import io.element.android.tests.testutils.EnsureNeverCalledWithTwoParams import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.clickOn import kotlinx.collections.immutable.persistentListOf import org.junit.Rule import org.junit.Test @@ -97,6 +101,47 @@ class TimelineViewTest { rule.onNodeWithContentDescription(contentDescription).performClick() eventsRecorder.assertSingle(TimelineEvents.JumpToLive) } + + @Test + fun `show shield dialog`() { + val eventsRecorder = EventsRecorder() + rule.setTimelineView( + state = aTimelineState( + timelineItems = persistentListOf( + aTimelineItemEvent( + // Do not use a Text because EditorStyledText cannot be used in UI test. + content = aTimelineItemImageContent(), + messageShield = MessageShield.UnverifiedIdentity(true), + ), + ), + eventSink = eventsRecorder, + ), + ) + val contentDescription = rule.activity.getString(CommonStrings.event_shield_reason_unverified_identity) + rule.onNodeWithContentDescription(contentDescription).performClick() + eventsRecorder.assertList( + listOf( + TimelineEvents.OnScrollFinished(0), + TimelineEvents.OnScrollFinished(0), + TimelineEvents.OnScrollFinished(0), + TimelineEvents.ShowShieldDialog(MessageShield.UnverifiedIdentity(true)), + ) + ) + } + + @Test + fun `hide shield dialog`() { + val eventsRecorder = EventsRecorder() + rule.setTimelineView( + state = aTimelineState( + isLive = false, + eventSink = eventsRecorder, + messageShield = aCriticalShield(), + ), + ) + rule.clickOn(CommonStrings.action_ok) + eventsRecorder.assertSingle(TimelineEvents.HideShieldDialog) + } } private fun AndroidComposeTestRule.setTimelineView( From 459f60d8a04b9b0541e896534600217e25615ef4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Aug 2024 11:33:52 +0200 Subject: [PATCH 120/186] Add preview for message shield dialog. --- .../TimelineViewMessageShieldPreview.kt | 62 +++++++++++++++++++ .../tests/konsist/KonsistPreviewTest.kt | 1 + 2 files changed, 63 insertions(+) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewMessageShieldPreview.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewMessageShieldPreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewMessageShieldPreview.kt new file mode 100644 index 0000000000..68baf476a3 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewMessageShieldPreview.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.timeline + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import io.element.android.features.messages.impl.timeline.components.aCriticalShield +import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories +import io.element.android.features.messages.impl.timeline.di.aFakeTimelineItemPresenterFactories +import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent +import io.element.android.features.messages.impl.typing.aTypingNotificationState +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import kotlinx.collections.immutable.toImmutableList + +@PreviewsDayNight +@Composable +internal fun TimelineViewMessageShieldPreview() = ElementPreview { + val timelineItems = aTimelineItemList(aTimelineItemTextContent()) + // For consistency, ensure that there is a message in the timeline (the last one) with an error. + val messageShield = aCriticalShield() + val items = listOf( + (timelineItems.first() as TimelineItem.Event).copy(messageShield = messageShield) + ) + timelineItems.drop(1) + CompositionLocalProvider( + LocalTimelineItemPresenterFactories provides aFakeTimelineItemPresenterFactories(), + ) { + TimelineView( + state = aTimelineState( + timelineItems = items.toImmutableList(), + messageShield = messageShield, + ), + typingNotificationState = aTypingNotificationState(), + onUserDataClick = {}, + onLinkClick = {}, + onMessageClick = {}, + onMessageLongClick = {}, + onSwipeToReply = {}, + onReactionClick = { _, _ -> }, + onReactionLongClick = { _, _ -> }, + onMoreReactionsClick = {}, + onReadReceiptClick = {}, + onJoinCallClick = {}, + forceJumpToBottomVisibility = true, + ) + } +} 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 3fb609b0b5..a64fdaa84c 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 @@ -129,6 +129,7 @@ class KonsistPreviewTest { "TimelineItemGroupedEventsRowContentExpandedPreview", "TimelineItemVoiceViewUnifiedPreview", "TimelineVideoWithCaptionRowPreview", + "TimelineViewMessageShieldPreview", "UserAvatarColorsPreview", ) .assertTrue( From cbc59e075e389b3061eb77df3596bda8d0ad74a7 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 16 Aug 2024 09:44:36 +0000 Subject: [PATCH 121/186] Update screenshots --- ...ssages.impl.timeline_TimelineViewMessageShield_Day_0_en.png | 3 +++ ...ages.impl.timeline_TimelineViewMessageShield_Night_0_en.png | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en.png new file mode 100644 index 0000000000..d07f02067d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71f9d463136dd01c40bd11d5c4ea571ce65dd4c42f0c724e8c6c4ffec3eb6fa6 +size 37341 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en.png new file mode 100644 index 0000000000..b59834d849 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1cee48ed80d4a6318e2b1b04873f1f59cab81f7f18046d3d4d31dc27eb26544 +size 35166 From 70558aa381b55acb36cd80cbeda03d8a3c3f9d01 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 12 Aug 2024 09:44:05 +0200 Subject: [PATCH 122/186] Move editMessageLambda to the constructor. --- .../impl/textcomposer/MessageComposerPresenterTest.kt | 7 +++---- .../android/libraries/matrix/test/room/FakeMatrixRoom.kt | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt index dcb09fb7c8..924616de7a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt @@ -431,10 +431,9 @@ class MessageComposerPresenterTest { } val fakeMatrixRoom = FakeMatrixRoom( liveTimeline = timeline, - typingNoticeResult = { Result.success(Unit) } - ).apply { - this.editMessageLambda = roomEditMessageLambda - } + typingNoticeResult = { Result.success(Unit) }, + editMessageLambda = roomEditMessageLambda, + ) val presenter = createPresenter( this, fakeMatrixRoom, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 955e9b64c5..1e7eb8c003 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -105,6 +105,7 @@ class FakeMatrixRoom( private val setTopicResult: (String) -> Result = { lambdaError() }, private val updateAvatarResult: (String, ByteArray) -> Result = { _, _ -> lambdaError() }, private val removeAvatarResult: () -> Result = { lambdaError() }, + private val editMessageLambda: (EventId, String, String?, List) -> Result = { _, _, _, _ -> lambdaError() }, private val sendMessageResult: (String, String?, List) -> Result = { _, _, _ -> lambdaError() }, private val updateUserRoleResult: () -> Result = { lambdaError() }, private val toggleReactionResult: (String, EventId) -> Result = { _, _ -> lambdaError() }, @@ -221,9 +222,8 @@ class FakeMatrixRoom( return updateUserRoleResult() } - var editMessageLambda: (EventId, String, String?, List) -> Result = { _, _, _, _ -> lambdaError() } - override suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List): Result { - return editMessageLambda(eventId, body, htmlBody, mentions) + override suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List) = simulateLongTask { + editMessageLambda(eventId, body, htmlBody, mentions) } override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List) = simulateLongTask { From 25eb1fa7a42ac0d64821f68b0924944080ef3c7e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 12 Aug 2024 10:19:10 +0200 Subject: [PATCH 123/186] Default value to redact own message should be true. --- .../android/features/messages/impl/UserEventPermissions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 77a24b8c5d..25d06add8d 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 @@ -29,7 +29,7 @@ data class UserEventPermissions( ) { companion object { val DEFAULT = UserEventPermissions( - canRedactOwn = false, + canRedactOwn = true, canRedactOther = false, canSendMessage = true, canSendReaction = true, From 6776df8b408b5d19e3cd801d48f91132e836ba9c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 12 Aug 2024 10:40:34 +0200 Subject: [PATCH 124/186] Remove useless Boxes. --- .../pinned/banner/PinnedMessagesBannerView.kt | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index e925220796..d466f1c20f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -71,16 +71,15 @@ fun PinnedMessagesBannerView( onViewAllClick: () -> Unit, modifier: Modifier = Modifier, ) { - Box(modifier = modifier) { - when (state) { - PinnedMessagesBannerState.Hidden -> Unit - is PinnedMessagesBannerState.Visible -> { - PinnedMessagesBannerRow( - state = state, - onClick = onClick, - onViewAllClick = onViewAllClick, - ) - } + when (state) { + PinnedMessagesBannerState.Hidden -> Unit + is PinnedMessagesBannerState.Visible -> { + PinnedMessagesBannerRow( + state = state, + onClick = onClick, + onViewAllClick = onViewAllClick, + modifier = modifier, + ) } } } @@ -136,18 +135,17 @@ private fun ViewAllButton( onViewAllClick: () -> Unit, modifier: Modifier = Modifier, ) { - Box(modifier = modifier) { - val text = if (state is PinnedMessagesBannerState.Loaded) { - stringResource(id = CommonStrings.screen_room_pinned_banner_view_all_button_title) - } else { - "" - } - TextButton( - text = text, - showProgress = state is PinnedMessagesBannerState.Loading, - onClick = onViewAllClick - ) + val text = if (state is PinnedMessagesBannerState.Loaded) { + stringResource(id = CommonStrings.screen_room_pinned_banner_view_all_button_title) + } else { + "" } + TextButton( + text = text, + showProgress = state is PinnedMessagesBannerState.Loading, + onClick = onViewAllClick, + modifier = modifier, + ) } private fun Modifier.drawBorder(borderColor: Color): Modifier { From f7d8e127aaf9cfdf77833433f371bd4ed4945786 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Aug 2024 12:26:39 +0200 Subject: [PATCH 125/186] Add unit test for DefaultPinnedMessagesBannerFormatter --- ...efaultPinnedMessagesBannerFormatterTest.kt | 799 ++++++++++++++++++ 1 file changed, 799 insertions(+) create mode 100644 libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt new file mode 100644 index 0000000000..2bf96de7c1 --- /dev/null +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt @@ -0,0 +1,799 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.eventformatter.impl + +import android.content.Context +import androidx.compose.ui.text.AnnotatedString +import com.google.common.truth.Truth.assertThat +import com.google.common.truth.Truth.assertWithMessage +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.media.ImageInfo +import io.element.android.libraries.matrix.api.media.MediaSource +import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.EventContent +import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent +import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent +import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.LocationMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange +import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent +import io.element.android.libraries.matrix.api.timeline.item.event.MessageType +import io.element.android.libraries.matrix.api.timeline.item.event.NoticeMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.OtherMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.OtherState +import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent +import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent +import io.element.android.libraries.matrix.api.timeline.item.event.StateContent +import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent +import io.element.android.libraries.matrix.api.timeline.item.event.StickerMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent +import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent +import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.media.aMediaSource +import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser +import io.element.android.libraries.matrix.test.timeline.aPollContent +import io.element.android.libraries.matrix.test.timeline.aProfileChangeMessageContent +import io.element.android.libraries.matrix.test.timeline.aProfileTimelineDetails +import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.services.toolbox.impl.strings.AndroidStringProvider +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config + +@Suppress("LargeClass") +@RunWith(RobolectricTestRunner::class) +class DefaultPinnedMessagesBannerFormatterTest { + private lateinit var context: Context + private lateinit var fakeMatrixClient: FakeMatrixClient + private lateinit var formatter: DefaultPinnedMessagesBannerFormatter + private lateinit var unsupportedEvent: String + + @Before + fun setup() { + context = RuntimeEnvironment.getApplication() as Context + fakeMatrixClient = FakeMatrixClient() + val stringProvider = AndroidStringProvider(context.resources) + formatter = DefaultPinnedMessagesBannerFormatter( + sp = stringProvider, + permalinkParser = FakePermalinkParser(), + ) + unsupportedEvent = stringProvider.getString(CommonStrings.common_unsupported_event) + } + + @Test + @Config(qualifiers = "en") + fun `Redacted content`() { + val expected = "Message removed" + val senderName = "Someone" + val message = createRoomEvent(false, senderName, RedactedContent) + val result = formatter.format(message) + assertThat(result).isEqualTo(expected) + } + + @Test + @Config(qualifiers = "en") + fun `Sticker content`() { + val body = "a sticker body" + val info = ImageInfo(null, null, null, null, null, null, null) + val message = createRoomEvent(false, null, StickerContent(body, info, aMediaSource(url = "url"))) + val result = formatter.format(message) + val expectedBody = "Sticker: a sticker body" + assertThat(result.toString()).isEqualTo(expectedBody) + } + + @Test + @Config(qualifiers = "en") + fun `Unable to decrypt content`() { + val expected = "Waiting for this message" + val senderName = "Someone" + val message = createRoomEvent(false, senderName, UnableToDecryptContent(UnableToDecryptContent.Data.Unknown)) + val result = formatter.format(message) + assertThat(result).isEqualTo(expected) + } + + @Test + @Config(qualifiers = "en") + fun `FailedToParseMessageLike, FailedToParseState & Unknown content`() { + val senderName = "Someone" + sequenceOf( + FailedToParseMessageLikeContent("", ""), + FailedToParseStateContent("", "", ""), + UnknownContent, + ).forEach { type -> + val message = createRoomEvent(false, senderName, type) + val result = formatter.format(message) + assertWithMessage("$type was not properly handled").that(result).isEqualTo(unsupportedEvent) + } + } + + // region Message contents + + @Test + @Config(qualifiers = "en") + fun `Message contents`() { + val body = "Shared body" + fun createMessageContent(type: MessageType): MessageContent { + return MessageContent(body, null, false, false, type) + } + + val sharedContentMessagesTypes = arrayOf( + TextMessageType(body, null), + VideoMessageType(body, null, null, MediaSource("url"), null), + AudioMessageType(body, MediaSource("url"), null), + VoiceMessageType(body, MediaSource("url"), null, null), + ImageMessageType(body, null, null, MediaSource("url"), null), + StickerMessageType(body, MediaSource("url"), null), + FileMessageType(body, MediaSource("url"), null), + LocationMessageType(body, "geo:1,2", null), + NoticeMessageType(body, null), + EmoteMessageType(body, null), + OtherMessageType(msgType = "a_type", body = body), + ) + val results = mutableListOf>() + + sharedContentMessagesTypes.forEach { type -> + val content = createMessageContent(type) + val message = createRoomEvent(sentByYou = false, senderDisplayName = "Someone", content = content) + val result = formatter.format(message) + results.add(type to result) + } + + // Verify results type + for ((type, result) in results) { + val expectedResult = when (type) { + is VideoMessageType, + is AudioMessageType, + is VoiceMessageType, + is ImageMessageType, + is StickerMessageType, + is FileMessageType, + is LocationMessageType -> AnnotatedString::class.java + is EmoteMessageType, + is TextMessageType, + is NoticeMessageType, + is OtherMessageType -> String::class.java + } + assertThat(result).isInstanceOf(expectedResult) + } + // Verify results content + for ((type, result) in results) { + val expectedResult = when (type) { + is VideoMessageType -> "Video: Shared body" + is AudioMessageType -> "Audio: Shared body" + is VoiceMessageType -> "Voice message: Shared body" + is ImageMessageType -> "Image: Shared body" + is StickerMessageType -> "Sticker: Shared body" + is FileMessageType -> "File: Shared body" + is LocationMessageType -> "Shared location: Shared body" + is EmoteMessageType -> "* Someone ${type.body}" + is TextMessageType, + is NoticeMessageType, + is OtherMessageType -> body + } + assertWithMessage("$type was not properly handled").that(result.toString()).isEqualTo(expectedResult) + } + } + + // endregion + + // region Membership change + + @Test + @Config(qualifiers = "en") + fun `Membership change - joined`() { + val otherName = "Other" + val youContent = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.JOINED) + + val youJoinedRoomEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youJoinedRoom = formatter.format(youJoinedRoomEvent) + assertThat(youJoinedRoom).isEqualTo(unsupportedEvent) + + val someoneJoinedRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneJoinedRoom = formatter.format(someoneJoinedRoomEvent) + assertThat(someoneJoinedRoom).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - left`() { + val otherName = "Other" + val youContent = RoomMembershipContent(A_USER_ID, null, MembershipChange.LEFT) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.LEFT) + + val youLeftRoomEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youLeftRoom = formatter.format(youLeftRoomEvent) + assertThat(youLeftRoom).isEqualTo(unsupportedEvent) + + val someoneLeftRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneLeftRoom = formatter.format(someoneLeftRoomEvent) + assertThat(someoneLeftRoom).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - banned`() { + val otherName = "Other" + val third = "Someone" + val youContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.BANNED) + val youKickedContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KICKED_AND_BANNED) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.BANNED) + val someoneKickedContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KICKED_AND_BANNED) + + val youBannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youBanned = formatter.format(youBannedEvent) + assertThat(youBanned).isEqualTo(unsupportedEvent) + + val youKickBannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youKickedContent) + val youKickedBanned = formatter.format(youKickBannedEvent) + assertThat(youKickedBanned).isEqualTo(unsupportedEvent) + + val someoneBannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneBanned = formatter.format(someoneBannedEvent) + assertThat(someoneBanned).isEqualTo(unsupportedEvent) + + val someoneKickBannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneKickedContent) + val someoneKickBanned = formatter.format(someoneKickBannedEvent) + assertThat(someoneKickBanned).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - unban`() { + val otherName = "Other" + val third = "Someone" + val youContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.UNBANNED) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.UNBANNED) + + val youUnbannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youUnbanned = formatter.format(youUnbannedEvent) + assertThat(youUnbanned).isEqualTo(unsupportedEvent) + + val someoneUnbannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneUnbanned = formatter.format(someoneUnbannedEvent) + assertThat(someoneUnbanned).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - kicked`() { + val otherName = "Other" + val third = "Someone" + val youContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KICKED) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KICKED) + + val youKickedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youKicked = formatter.format(youKickedEvent) + assertThat(youKicked).isEqualTo(unsupportedEvent) + + val someoneKickedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneKicked = formatter.format(someoneKickedEvent) + assertThat(someoneKicked).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - invited`() { + val otherName = "Other" + val third = "Someone" + val youContent = RoomMembershipContent(A_USER_ID, null, MembershipChange.INVITED) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.INVITED) + + val youWereInvitedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = youContent) + val youWereInvited = formatter.format(youWereInvitedEvent) + assertThat(youWereInvited).isEqualTo(unsupportedEvent) + + val youInvitedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) + val youInvited = formatter.format(youInvitedEvent) + assertThat(youInvited).isEqualTo(unsupportedEvent) + + val someoneInvitedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneInvited = formatter.format(someoneInvitedEvent) + assertThat(someoneInvited).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - invitation accepted`() { + val otherName = "Other" + val youContent = RoomMembershipContent(A_USER_ID, null, MembershipChange.INVITATION_ACCEPTED) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.INVITATION_ACCEPTED) + + val youAcceptedInviteEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youAcceptedInvite = formatter.format(youAcceptedInviteEvent) + assertThat(youAcceptedInvite).isEqualTo(unsupportedEvent) + + val someoneAcceptedInviteEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneAcceptedInvite = formatter.format(someoneAcceptedInviteEvent) + assertThat(someoneAcceptedInvite).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - invitation rejected`() { + val otherName = "Other" + val youContent = RoomMembershipContent(A_USER_ID, null, MembershipChange.INVITATION_REJECTED) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.INVITATION_REJECTED) + + val youRejectedInviteEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youRejectedInvite = formatter.format(youRejectedInviteEvent) + assertThat(youRejectedInvite).isEqualTo(unsupportedEvent) + + val someoneRejectedInviteEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneRejectedInvite = formatter.format(someoneRejectedInviteEvent) + assertThat(someoneRejectedInvite).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - invitation revoked`() { + val otherName = "Other" + val third = "Someone" + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.INVITATION_REVOKED) + + val youRevokedInviteEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) + val youRevokedInvite = formatter.format(youRevokedInviteEvent) + assertThat(youRevokedInvite).isEqualTo(unsupportedEvent) + + val someoneRevokedInviteEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneRevokedInvite = formatter.format(someoneRevokedInviteEvent) + assertThat(someoneRevokedInvite).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - knocked`() { + val otherName = "Other" + val youContent = RoomMembershipContent(A_USER_ID, null, MembershipChange.KNOCKED) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.KNOCKED) + + val youKnockedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youKnocked = formatter.format(youKnockedEvent) + assertThat(youKnocked).isEqualTo(unsupportedEvent) + + val someoneKnockedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneKnocked = formatter.format(someoneKnockedEvent) + assertThat(someoneKnocked).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - knock accepted`() { + val otherName = "Other" + val third = "Someone" + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KNOCK_ACCEPTED) + + val youAcceptedKnockEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) + val youAcceptedKnock = formatter.format(youAcceptedKnockEvent) + assertThat(youAcceptedKnock).isEqualTo(unsupportedEvent) + + val someoneAcceptedKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneAcceptedKnock = formatter.format(someoneAcceptedKnockEvent) + assertThat(someoneAcceptedKnock).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - knock retracted`() { + val otherName = "Other" + val youContent = RoomMembershipContent(A_USER_ID, null, MembershipChange.KNOCK_RETRACTED) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), null, MembershipChange.KNOCK_RETRACTED) + + val youRetractedKnockEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youRetractedKnock = formatter.format(youRetractedKnockEvent) + assertThat(youRetractedKnock).isEqualTo(unsupportedEvent) + + val someoneRetractedKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneRetractedKnock = formatter.format(someoneRetractedKnockEvent) + assertThat(someoneRetractedKnock).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - knock denied`() { + val otherName = "Other" + val third = "Someone" + val youContent = RoomMembershipContent(A_USER_ID, third, MembershipChange.KNOCK_DENIED) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KNOCK_DENIED) + + val youDeniedKnockEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) + val youDeniedKnock = formatter.format(youDeniedKnockEvent) + assertThat(youDeniedKnock).isEqualTo(unsupportedEvent) + + val someoneDeniedKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneDeniedKnock = formatter.format(someoneDeniedKnockEvent) + assertThat(someoneDeniedKnock).isEqualTo(unsupportedEvent) + + val someoneDeniedYourKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = youContent) + val someoneDeniedYourKnock = formatter.format(someoneDeniedYourKnockEvent) + assertThat(someoneDeniedYourKnock).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - None`() { + val otherName = "Other" + val youContent = RoomMembershipContent(A_USER_ID, null, MembershipChange.NONE) + val someoneContent = RoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.NONE) + + val youNoneRoomEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youNoneRoom = formatter.format(youNoneRoomEvent) + assertThat(youNoneRoom).isEqualTo(unsupportedEvent) + + val someoneNoneRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneNoneRoom = formatter.format(someoneNoneRoomEvent) + assertThat(someoneNoneRoom).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Membership change - others`() { + val otherChanges = arrayOf(MembershipChange.ERROR, MembershipChange.NOT_IMPLEMENTED, null) + + val results = otherChanges.map { change -> + val content = RoomMembershipContent(A_USER_ID, null, change) + val event = createRoomEvent(sentByYou = false, senderDisplayName = "Someone", content = content) + val result = formatter.format(event) + change to result + } + val expected = otherChanges.map { it to unsupportedEvent } + assertThat(results).isEqualTo(expected) + } + + // endregion + + // region Room State + + @Test + @Config(qualifiers = "en") + fun `Room state change - avatar`() { + val otherName = "Other" + val changedContent = StateContent("", OtherState.RoomAvatar("new_avatar")) + val removedContent = StateContent("", OtherState.RoomAvatar(null)) + + val youChangedRoomAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedRoomAvatar = formatter.format(youChangedRoomAvatarEvent) + assertThat(youChangedRoomAvatar).isEqualTo(unsupportedEvent) + + val someoneChangedRoomAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneChangedRoomAvatar = formatter.format(someoneChangedRoomAvatarEvent) + assertThat(someoneChangedRoomAvatar).isEqualTo(unsupportedEvent) + + val youRemovedRoomAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youRemovedRoomAvatar = formatter.format(youRemovedRoomAvatarEvent) + assertThat(youRemovedRoomAvatar).isEqualTo(unsupportedEvent) + + val someoneRemovedRoomAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneRemovedRoomAvatar = formatter.format(someoneRemovedRoomAvatarEvent) + assertThat(someoneRemovedRoomAvatar).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Room state change - create`() { + val otherName = "Other" + val content = StateContent("", OtherState.RoomCreate) + + val youCreatedRoomMessage = createRoomEvent(sentByYou = true, senderDisplayName = null, content = content) + val youCreatedRoom = formatter.format(youCreatedRoomMessage) + assertThat(youCreatedRoom).isEqualTo(unsupportedEvent) + + val someoneCreatedRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = content) + val someoneCreatedRoom = formatter.format(someoneCreatedRoomEvent) + assertThat(someoneCreatedRoom).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Room state change - encryption`() { + val otherName = "Other" + val content = StateContent("", OtherState.RoomEncryption) + + val youCreatedRoomMessage = createRoomEvent(sentByYou = true, senderDisplayName = null, content = content) + val youCreatedRoom = formatter.format(youCreatedRoomMessage) + assertThat(youCreatedRoom).isEqualTo(unsupportedEvent) + + val someoneCreatedRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = content) + val someoneCreatedRoom = formatter.format(someoneCreatedRoomEvent) + assertThat(someoneCreatedRoom).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Room state change - room name`() { + val otherName = "Other" + val newName = "New name" + val changedContent = StateContent("", OtherState.RoomName(newName)) + val removedContent = StateContent("", OtherState.RoomName(null)) + + val youChangedRoomNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedRoomName = formatter.format(youChangedRoomNameEvent) + assertThat(youChangedRoomName).isEqualTo(unsupportedEvent) + + val someoneChangedRoomNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneChangedRoomName = formatter.format(someoneChangedRoomNameEvent) + assertThat(someoneChangedRoomName).isEqualTo(unsupportedEvent) + + val youRemovedRoomNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youRemovedRoomName = formatter.format(youRemovedRoomNameEvent) + assertThat(youRemovedRoomName).isEqualTo(unsupportedEvent) + + val someoneRemovedRoomNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneRemovedRoomName = formatter.format(someoneRemovedRoomNameEvent) + assertThat(someoneRemovedRoomName).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Room state change - third party invite`() { + val otherName = "Other" + val inviteeName = "Alice" + val changedContent = StateContent("", OtherState.RoomThirdPartyInvite(inviteeName)) + val removedContent = StateContent("", OtherState.RoomThirdPartyInvite(null)) + + val youInvitedSomeoneEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youInvitedSomeone = formatter.format(youInvitedSomeoneEvent) + assertThat(youInvitedSomeone).isEqualTo(unsupportedEvent) + + val someoneInvitedSomeoneEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneInvitedSomeone = formatter.format(someoneInvitedSomeoneEvent) + assertThat(someoneInvitedSomeone).isEqualTo(unsupportedEvent) + + val youInvitedNoOneEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youInvitedNoOne = formatter.format(youInvitedNoOneEvent) + assertThat(youInvitedNoOne).isEqualTo(unsupportedEvent) + + val someoneInvitedNoOneEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneInvitedNoOne = formatter.format(someoneInvitedNoOneEvent) + assertThat(someoneInvitedNoOne).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Room state change - room topic`() { + val otherName = "Other" + val roomTopic = "New topic" + val changedContent = StateContent("", OtherState.RoomTopic(roomTopic)) + val removedContent = StateContent("", OtherState.RoomTopic(null)) + + val youChangedRoomTopicEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedRoomTopic = formatter.format(youChangedRoomTopicEvent) + assertThat(youChangedRoomTopic).isEqualTo(unsupportedEvent) + + val someoneChangedRoomTopicEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneChangedRoomTopic = formatter.format(someoneChangedRoomTopicEvent) + assertThat(someoneChangedRoomTopic).isEqualTo(unsupportedEvent) + + val youRemovedRoomTopicEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youRemovedRoomTopic = formatter.format(youRemovedRoomTopicEvent) + assertThat(youRemovedRoomTopic).isEqualTo(unsupportedEvent) + + val someoneRemovedRoomTopicEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneRemovedRoomTopic = formatter.format(someoneRemovedRoomTopicEvent) + assertThat(someoneRemovedRoomTopic).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Room state change - others must return null`() { + val otherStates = arrayOf( + OtherState.PolicyRuleRoom, + OtherState.PolicyRuleServer, + OtherState.PolicyRuleUser, + OtherState.RoomAliases, + OtherState.RoomCanonicalAlias, + OtherState.RoomGuestAccess, + OtherState.RoomHistoryVisibility, + OtherState.RoomJoinRules, + OtherState.RoomPinnedEvents(OtherState.RoomPinnedEvents.Change.CHANGED), + OtherState.RoomUserPowerLevels(emptyMap()), + OtherState.RoomServerAcl, + OtherState.RoomTombstone, + OtherState.SpaceChild, + OtherState.SpaceParent, + OtherState.Custom("custom_event_type") + ) + + val results = otherStates.map { state -> + val content = StateContent("", state) + val event = createRoomEvent(sentByYou = false, senderDisplayName = "Someone", content = content) + val result = formatter.format(event) + state to result + } + val expected = otherStates.map { it to unsupportedEvent } + assertThat(results).isEqualTo(expected) + } + + // endregion + + // region Profile change + + @Test + @Config(qualifiers = "en") + fun `Profile change - avatar`() { + val otherName = "Other" + val changedContent = aProfileChangeMessageContent(avatarUrl = "new_avatar_url", prevAvatarUrl = "old_avatar_url") + val setContent = aProfileChangeMessageContent(avatarUrl = "new_avatar_url", prevAvatarUrl = null) + val removedContent = aProfileChangeMessageContent(avatarUrl = null, prevAvatarUrl = "old_avatar_url") + val invalidContent = aProfileChangeMessageContent(avatarUrl = null, prevAvatarUrl = null) + val sameContent = aProfileChangeMessageContent(avatarUrl = "same_avatar_url", prevAvatarUrl = "same_avatar_url") + + val youChangedAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedAvatar = formatter.format(youChangedAvatarEvent) + assertThat(youChangedAvatar).isEqualTo(unsupportedEvent) + + val someoneChangeAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneChangeAvatar = formatter.format(someoneChangeAvatarEvent) + assertThat(someoneChangeAvatar).isEqualTo(unsupportedEvent) + + val youSetAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = setContent) + val youSetAvatar = formatter.format(youSetAvatarEvent) + assertThat(youSetAvatar).isEqualTo(unsupportedEvent) + + val someoneSetAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = setContent) + val someoneSetAvatar = formatter.format(someoneSetAvatarEvent) + assertThat(someoneSetAvatar).isEqualTo(unsupportedEvent) + + val youRemovedAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youRemovedAvatar = formatter.format(youRemovedAvatarEvent) + assertThat(youRemovedAvatar).isEqualTo(unsupportedEvent) + + val someoneRemovedAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneRemovedAvatar = formatter.format(someoneRemovedAvatarEvent) + assertThat(someoneRemovedAvatar).isEqualTo(unsupportedEvent) + + val unchangedEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = sameContent) + val unchangedResult = formatter.format(unchangedEvent) + assertThat(unchangedResult).isEqualTo(unsupportedEvent) + + val invalidEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = invalidContent) + val invalidResult = formatter.format(invalidEvent) + assertThat(invalidResult).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Profile change - display name`() { + val newDisplayName = "New" + val oldDisplayName = "Old" + val otherName = "Other" + val changedContent = aProfileChangeMessageContent(displayName = newDisplayName, prevDisplayName = oldDisplayName) + val setContent = aProfileChangeMessageContent(displayName = newDisplayName, prevDisplayName = null) + val removedContent = aProfileChangeMessageContent(displayName = null, prevDisplayName = oldDisplayName) + val sameContent = aProfileChangeMessageContent(displayName = newDisplayName, prevDisplayName = newDisplayName) + val invalidContent = aProfileChangeMessageContent(displayName = null, prevDisplayName = null) + + val youChangedDisplayNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedDisplayName = formatter.format(youChangedDisplayNameEvent) + assertThat(youChangedDisplayName).isEqualTo(unsupportedEvent) + + val someoneChangedDisplayNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneChangedDisplayName = formatter.format(someoneChangedDisplayNameEvent) + assertThat(someoneChangedDisplayName).isEqualTo(unsupportedEvent) + + val youSetDisplayNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = setContent) + val youSetDisplayName = formatter.format(youSetDisplayNameEvent) + assertThat(youSetDisplayName).isEqualTo(unsupportedEvent) + + val someoneSetDisplayNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = setContent) + val someoneSetDisplayName = formatter.format(someoneSetDisplayNameEvent) + assertThat(someoneSetDisplayName).isEqualTo(unsupportedEvent) + + val youRemovedDisplayNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youRemovedDisplayName = formatter.format(youRemovedDisplayNameEvent) + assertThat(youRemovedDisplayName).isEqualTo(unsupportedEvent) + + val someoneRemovedDisplayNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneRemovedDisplayName = formatter.format(someoneRemovedDisplayNameEvent) + assertThat(someoneRemovedDisplayName).isEqualTo(unsupportedEvent) + + val unchangedEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = sameContent) + val unchangedResult = formatter.format(unchangedEvent) + assertThat(unchangedResult).isEqualTo(unsupportedEvent) + + val invalidEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = invalidContent) + val invalidResult = formatter.format(invalidEvent) + assertThat(invalidResult).isEqualTo(unsupportedEvent) + } + + @Test + @Config(qualifiers = "en") + fun `Profile change - display name & avatar`() { + val newDisplayName = "New" + val oldDisplayName = "Old" + val changedContent = aProfileChangeMessageContent( + displayName = newDisplayName, + prevDisplayName = oldDisplayName, + avatarUrl = "new_avatar_url", + prevAvatarUrl = "old_avatar_url", + ) + val invalidContent = aProfileChangeMessageContent( + displayName = null, + prevDisplayName = null, + avatarUrl = null, + prevAvatarUrl = null, + ) + val sameContent = aProfileChangeMessageContent( + displayName = newDisplayName, + prevDisplayName = newDisplayName, + avatarUrl = "same_avatar_url", + prevAvatarUrl = "same_avatar_url", + ) + + val youChangedBothEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedBoth = formatter.format(youChangedBothEvent) + assertThat(youChangedBoth).isEqualTo(unsupportedEvent) + + val invalidContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = invalidContent) + val invalidMessage = formatter.format(invalidContentEvent) + assertThat(invalidMessage).isEqualTo(unsupportedEvent) + + val sameContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = sameContent) + val sameMessage = formatter.format(sameContentEvent) + assertThat(sameMessage).isEqualTo(unsupportedEvent) + } + + // endregion + + // region Polls + + @Test + @Config(qualifiers = "en") + fun `Computes last message for poll`() { + val pollContent = aPollContent() + + val mineContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = "Alice", content = pollContent) + val result = formatter.format(mineContentEvent) + assertThat(result).isInstanceOf(AnnotatedString::class.java) + assertThat(result.toString()).isEqualTo("Poll: Do you like polls?") + + val contentEvent = createRoomEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent) + val result2 = formatter.format(contentEvent) + assertThat(result2).isInstanceOf(AnnotatedString::class.java) + assertThat(result2.toString()).isEqualTo("Poll: Do you like polls?") + } + + // endregion + + private fun createRoomEvent( + sentByYou: Boolean, + senderDisplayName: String?, + content: EventContent, + ): EventTimelineItem { + val sender = if (sentByYou) A_USER_ID else someoneElseId + val profile = aProfileTimelineDetails(senderDisplayName) + return anEventTimelineItem( + content = content, + senderProfile = profile, + sender = sender, + isOwn = sentByYou, + ) + } + + private val someoneElseId = UserId("@someone_else:domain") +} From 3e674480060e67d5f4e57252a3521141421d8314 Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:25:36 +0000 Subject: [PATCH 126/186] Sync Strings from Localazy --- app/src/main/res/xml/locales_config.xml | 1 + .../src/main/res/values-nl/translations.xml | 6 + .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-nl/translations.xml | 10 + .../src/main/res/values-pl/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-nl/translations.xml | 6 + .../src/main/res/values-zh/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 14 + .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-nl/translations.xml | 11 + .../src/main/res/values-nl/translations.xml | 9 + .../src/main/res/values-nl/translations.xml | 6 + .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-nl/translations.xml | 4 + .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 14 + .../src/main/res/values-nl/translations.xml | 42 + .../src/main/res/values-zh/translations.xml | 16 +- .../src/main/res/values-nl/translations.xml | 8 + .../src/main/res/values-pl/translations.xml | 6 +- .../src/main/res/values-zh/translations.xml | 8 +- .../src/main/res/values-nl/translations.xml | 42 + .../src/main/res/values-pl/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-nl/translations.xml | 9 + .../src/main/res/values-nl/translations.xml | 11 + .../src/main/res/values-de/translations.xml | 3 + .../src/main/res/values-nl/translations.xml | 41 + .../src/main/res/values-zh/translations.xml | 8 +- .../src/main/res/values-nl/translations.xml | 7 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-nl/translations.xml | 15 + .../src/main/res/values-pl/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-nl/translations.xml | 45 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 2 + .../src/main/res/values-nl/translations.xml | 18 + .../src/main/res/values-zh/translations.xml | 14 +- .../src/main/res/values-be/translations.xml | 13 + .../src/main/res/values-cs/translations.xml | 13 + .../src/main/res/values-et/translations.xml | 13 + .../src/main/res/values-fr/translations.xml | 7 + .../src/main/res/values-hu/translations.xml | 12 + .../src/main/res/values-it/translations.xml | 12 + .../src/main/res/values-nl/translations.xml | 13 + .../src/main/res/values-pl/translations.xml | 12 + .../src/main/res/values-pt/translations.xml | 12 + .../src/main/res/values-ru/translations.xml | 13 + .../src/main/res/values-sk/translations.xml | 13 + .../src/main/res/values-sv/translations.xml | 13 + .../src/main/res/values-uk/translations.xml | 12 + .../src/main/res/values-zh/translations.xml | 14 +- .../src/main/res/values-nl/translations.xml | 8 + .../src/main/res/values-nl/translations.xml | 10 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-cs/translations.xml | 2 + .../src/main/res/values-fr/translations.xml | 2 + .../src/main/res/values-it/translations.xml | 2 + .../src/main/res/values-nl/translations.xml | 17 + .../src/main/res/values-pl/translations.xml | 2 + .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-nl/translations.xml | 4 + .../src/main/res/values-cs/translations.xml | 6 + .../src/main/res/values-fr/translations.xml | 6 + .../src/main/res/values-it/translations.xml | 6 + .../src/main/res/values-nl/translations.xml | 56 + .../src/main/res/values-pl/translations.xml | 6 + .../src/main/res/values-uz/translations.xml | 12 +- .../src/main/res/values-zh/translations.xml | 6 + .../src/main/res/values-nl/translations.xml | 4 + .../src/main/res/values-nl/translations.xml | 7 + .../src/main/res/values-de/translations.xml | 2 + .../src/main/res/values-nl/translations.xml | 50 + .../src/main/res/values-zh/translations.xml | 2 + .../src/main/res/values-nl/translations.xml | 25 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-be/translations.xml | 12 - .../src/main/res/values-cs/translations.xml | 12 + .../src/main/res/values-de/translations.xml | 15 + .../src/main/res/values-et/translations.xml | 16 +- .../src/main/res/values-fr/translations.xml | 20 + .../src/main/res/values-hu/translations.xml | 12 - .../src/main/res/values-it/translations.xml | 21 + .../src/main/res/values-nl/translations.xml | 218 +++ .../src/main/res/values-pl/translations.xml | 12 +- .../src/main/res/values-pt/translations.xml | 12 - .../src/main/res/values-ru/translations.xml | 12 - .../src/main/res/values-sk/translations.xml | 12 - .../src/main/res/values-sv/translations.xml | 12 - .../src/main/res/values-uk/translations.xml | 12 - .../src/main/res/values-zh/translations.xml | 44 +- plugins/src/main/kotlin/extension/locales.kt | 1 + .../appnav.loggedin_LoggedInView_Day_2_de.png | 4 +- ....qrcode.error_QrCodeErrorView_Day_0_de.png | 4 +- ....qrcode.error_QrCodeErrorView_Day_1_de.png | 4 +- ....qrcode.error_QrCodeErrorView_Day_2_de.png | 4 +- ....qrcode.error_QrCodeErrorView_Day_3_de.png | 4 +- ....qrcode.error_QrCodeErrorView_Day_5_de.png | 4 +- ...ns.qrcode.scan_QrCodeScanView_Day_3_de.png | 4 +- ...impl.actionlist_SheetContent_Day_11_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_2_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_3_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_4_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_5_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_6_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_7_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_8_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_9_de.png | 3 + ....components_MessageShieldView_Day_0_de.png | 3 + ...ts_TimelineItemCallNotifyView_Day_0_de.png | 4 +- ...ine_TimelineViewMessageShield_Day_0_de.png | 3 + ...typing_MessagesViewWithTyping_Day_0_de.png | 4 +- ...typing_MessagesViewWithTyping_Day_1_de.png | 4 +- ...typing_MessagesViewWithTyping_Day_2_de.png | 3 + ...es.messages.impl_MessagesView_Day_0_de.png | 3 + ...s.messages.impl_MessagesView_Day_10_de.png | 4 +- ...s.messages.impl_MessagesView_Day_11_de.png | 4 +- ...s.messages.impl_MessagesView_Day_12_de.png | 3 + ...s.messages.impl_MessagesView_Day_13_de.png | 3 + ...es.messages.impl_MessagesView_Day_1_de.png | 3 + ...es.messages.impl_MessagesView_Day_3_de.png | 4 +- ...es.messages.impl_MessagesView_Day_4_de.png | 4 +- ...es.messages.impl_MessagesView_Day_5_de.png | 3 + ...es.messages.impl_MessagesView_Day_6_de.png | 4 +- ...es.messages.impl_MessagesView_Day_7_de.png | 4 +- ...es.messages.impl_MessagesView_Day_8_de.png | 4 +- ...es.messages.impl_MessagesView_Day_9_de.png | 4 +- ...ferences.impl.about_AboutView_Day_1_de.png | 4 +- ...ons_NotificationSettingsView_Day_11_de.png | 4 +- ...lScreenIntentPermissionBanner_Day_0_de.png | 4 +- ...ord_ResetIdentityPasswordView_Day_0_de.png | 3 + ...ord_ResetIdentityPasswordView_Day_1_de.png | 3 + ...ord_ResetIdentityPasswordView_Day_2_de.png | 3 + ...ord_ResetIdentityPasswordView_Day_3_de.png | 3 + ...et.root_ResetIdentityRootView_Day_1_de.png | 3 + ...on.impl_VerifySelfSessionView_Day_0_de.png | 4 +- ...on.impl_VerifySelfSessionView_Day_1_de.png | 4 +- ...on.impl_VerifySelfSessionView_Day_7_de.png | 4 +- ...on.impl_VerifySelfSessionView_Day_8_de.png | 4 +- ....dialogs_AlertDialogContent_Dialogs_de.png | 3 + ...omponents.dialogs_AlertDialog_Day_0_de.png | 3 + ...ErrorDialogWithDoNotShowAgain_Day_0_de.png | 4 +- ...oomselect.impl_RoomSelectView_Day_5_de.png | 4 +- screenshots/html/data.js | 1164 +++++++++-------- 147 files changed, 1827 insertions(+), 790 deletions(-) create mode 100644 features/analytics/api/src/main/res/values-nl/translations.xml create mode 100644 features/analytics/impl/src/main/res/values-nl/translations.xml create mode 100644 features/call/impl/src/main/res/values-nl/translations.xml create mode 100644 features/createroom/impl/src/main/res/values-nl/translations.xml create mode 100644 features/ftue/impl/src/main/res/values-nl/translations.xml create mode 100644 features/invite/impl/src/main/res/values-nl/translations.xml create mode 100644 features/leaveroom/api/src/main/res/values-nl/translations.xml create mode 100644 features/lockscreen/impl/src/main/res/values-nl/translations.xml create mode 100644 features/login/impl/src/main/res/values-nl/translations.xml create mode 100644 features/logout/impl/src/main/res/values-nl/translations.xml create mode 100644 features/messages/impl/src/main/res/values-nl/translations.xml create mode 100644 features/onboarding/impl/src/main/res/values-nl/translations.xml create mode 100644 features/poll/impl/src/main/res/values-nl/translations.xml create mode 100644 features/preferences/impl/src/main/res/values-nl/translations.xml create mode 100644 features/rageshake/api/src/main/res/values-nl/translations.xml create mode 100644 features/rageshake/impl/src/main/res/values-nl/translations.xml create mode 100644 features/roomdetails/impl/src/main/res/values-nl/translations.xml create mode 100644 features/roomlist/impl/src/main/res/values-nl/translations.xml create mode 100644 features/securebackup/impl/src/main/res/values-nl/translations.xml create mode 100644 features/signedout/impl/src/main/res/values-nl/translations.xml create mode 100644 features/userprofile/shared/src/main/res/values-nl/translations.xml create mode 100644 features/verifysession/impl/src/main/res/values-nl/translations.xml create mode 100644 libraries/androidutils/src/main/res/values-nl/translations.xml create mode 100644 libraries/eventformatter/impl/src/main/res/values-nl/translations.xml create mode 100644 libraries/matrixui/src/main/res/values-nl/translations.xml create mode 100644 libraries/permissions/api/src/main/res/values-nl/translations.xml create mode 100644 libraries/push/impl/src/main/res/values-nl/translations.xml create mode 100644 libraries/textcomposer/impl/src/main/res/values-nl/translations.xml create mode 100644 libraries/ui-strings/src/main/res/values-nl/translations.xml create mode 100644 screenshots/de/features.messages.impl.actionlist_SheetContent_Day_11_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png create mode 100644 screenshots/de/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_de.png create mode 100644 screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_2_de.png create mode 100644 screenshots/de/features.messages.impl_MessagesView_Day_0_de.png create mode 100644 screenshots/de/features.messages.impl_MessagesView_Day_12_de.png create mode 100644 screenshots/de/features.messages.impl_MessagesView_Day_13_de.png create mode 100644 screenshots/de/features.messages.impl_MessagesView_Day_1_de.png create mode 100644 screenshots/de/features.messages.impl_MessagesView_Day_5_de.png create mode 100644 screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png create mode 100644 screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png create mode 100644 screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png create mode 100644 screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png create mode 100644 screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png create mode 100644 screenshots/de/libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_de.png create mode 100644 screenshots/de/libraries.designsystem.components.dialogs_AlertDialog_Day_0_de.png diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml index e49aa1e4a0..ad67e6746a 100644 --- a/app/src/main/res/xml/locales_config.xml +++ b/app/src/main/res/xml/locales_config.xml @@ -13,6 +13,7 @@ + diff --git a/features/analytics/api/src/main/res/values-nl/translations.xml b/features/analytics/api/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..fcd05769c5 --- /dev/null +++ b/features/analytics/api/src/main/res/values-nl/translations.xml @@ -0,0 +1,6 @@ + + + "Deel anonieme gebruiksgegevens om ons te helpen problemen te identificeren." + "Je kunt al onze voorwaarden %1$s lezen." + "hier" + diff --git a/features/analytics/api/src/main/res/values-pl/translations.xml b/features/analytics/api/src/main/res/values-pl/translations.xml index 9fd1f51683..a3347582cc 100644 --- a/features/analytics/api/src/main/res/values-pl/translations.xml +++ b/features/analytics/api/src/main/res/values-pl/translations.xml @@ -1,6 +1,6 @@ - "Udostępniaj anonimowe dane dotyczące użytkowania, aby pomóc nam identyfikować problemy." + "Udostępniaj anonimowe dane użytkowania, aby pomóc nam identyfikować problemy." "Przeczytaj nasze warunki użytkowania %1$s." "tutaj" "Udostępniaj dane analityczne" diff --git a/features/analytics/impl/src/main/res/values-nl/translations.xml b/features/analytics/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..dc45280bfe --- /dev/null +++ b/features/analytics/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,10 @@ + + + "We zullen geen persoonlijke gegevens registreren of er een profiel van maken" + "Deel anonieme gebruiksgegevens om ons te helpen problemen te identificeren." + "Je kunt al onze voorwaarden %1$s lezen." + "hier" + "Je kunt dit op elk moment uitschakelen" + "We delen je gegevens niet met derden" + "Help %1$s te verbeteren" + diff --git a/features/analytics/impl/src/main/res/values-pl/translations.xml b/features/analytics/impl/src/main/res/values-pl/translations.xml index 02faba157f..61da8408ad 100644 --- a/features/analytics/impl/src/main/res/values-pl/translations.xml +++ b/features/analytics/impl/src/main/res/values-pl/translations.xml @@ -1,10 +1,10 @@ "Nie będziemy rejestrować ani profilować żadnych danych osobistych" - "Udostępniaj anonimowe dane dotyczące użytkowania, aby pomóc nam identyfikować problemy." + "Udostępniaj anonimowe dane użytkowania, aby pomóc nam identyfikować problemy." "Przeczytaj nasze warunki użytkowania %1$s." "tutaj" "Możesz to wyłączyć w dowolnym momencie" - "Nie będziemy udostępniać Twoich danych podmiotom trzecim" + "Nie będziemy udostępniać Twoich danych stronom trzecim" "Pomóż nam ulepszyć %1$s" diff --git a/features/analytics/impl/src/main/res/values-zh/translations.xml b/features/analytics/impl/src/main/res/values-zh/translations.xml index 887930eac7..d18650654b 100644 --- a/features/analytics/impl/src/main/res/values-zh/translations.xml +++ b/features/analytics/impl/src/main/res/values-zh/translations.xml @@ -4,7 +4,7 @@ "共享匿名使用数据以帮助我们排查问题。" "您可以阅读我们的所有条款 %1$s。" "此处" - "你可以随时关闭此功能" + "可以随时关闭此功能" "我们不会与第三方共享您的数据" "帮助改进 %1$s" diff --git a/features/call/impl/src/main/res/values-nl/translations.xml b/features/call/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..dd39bb9fe6 --- /dev/null +++ b/features/call/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,6 @@ + + + "Actieve oproep" + "Tik om terug te gaan naar het gesprek" + "☎️ In gesprek" + diff --git a/features/call/impl/src/main/res/values-zh/translations.xml b/features/call/impl/src/main/res/values-zh/translations.xml index 4d57257d19..8eda0df212 100644 --- a/features/call/impl/src/main/res/values-zh/translations.xml +++ b/features/call/impl/src/main/res/values-zh/translations.xml @@ -3,4 +3,5 @@ "通话进行中" "点按即可返回通话" "☎️ 通话中" + "Element 来电" diff --git a/features/createroom/impl/src/main/res/values-nl/translations.xml b/features/createroom/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..2cdb3202a5 --- /dev/null +++ b/features/createroom/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,14 @@ + + + "Nieuwe kamer" + "Mensen uitnodigen" + "Er is een fout opgetreden bij het aanmaken van de kamer" + "Berichten in deze kamer zijn versleuteld. Versleuteling kan achteraf niet worden uitgeschakeld." + "Privé kamer (alleen op uitnodiging)" + "Berichten zijn niet versleuteld en iedereen kan ze lezen. Je kunt versleuteling later inschakelen." + "Openbare kamer (iedereen)" + "Naam van de kamer" + "Creëer een kamer" + "Onderwerp (optioneel)" + "Er is een fout opgetreden bij het starten van een chat" + diff --git a/features/createroom/impl/src/main/res/values-pl/translations.xml b/features/createroom/impl/src/main/res/values-pl/translations.xml index 37090055b9..e0b19a0c49 100644 --- a/features/createroom/impl/src/main/res/values-pl/translations.xml +++ b/features/createroom/impl/src/main/res/values-pl/translations.xml @@ -2,7 +2,7 @@ "Nowy pokój" "Zaproś znajomych" - "Wystąpił błąd podczas tworzenia pokoju" + "Wystąpił błąd w trakcie tworzenia pokoju" "Wiadomości w tym pokoju są szyfrowane. Szyfrowania nie można później wyłączyć." "Pokój prywatny (tylko zaproszenie)" "Wiadomości nie są szyfrowane i każdy może je odczytać. Możesz aktywować szyfrowanie później." diff --git a/features/createroom/impl/src/main/res/values-zh/translations.xml b/features/createroom/impl/src/main/res/values-zh/translations.xml index 4a5c2120a2..d398cfdbd0 100644 --- a/features/createroom/impl/src/main/res/values-zh/translations.xml +++ b/features/createroom/impl/src/main/res/values-zh/translations.xml @@ -5,7 +5,7 @@ "创建房间时出错" "此聊天室中的消息已加密。加密无法禁用。" "私人房间(仅限受邀者)" - "消息未加密,任何人都可以查看。你可以稍后启用加密。" + "消息未加密,任何人都可以查看。可以稍后启用加密。" "公共房间(任何人)" "房间名称" "创建房间" diff --git a/features/ftue/impl/src/main/res/values-nl/translations.xml b/features/ftue/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..1975f26467 --- /dev/null +++ b/features/ftue/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,11 @@ + + + "Je kunt je instellingen later wijzigen." + "Sta meldingen toe en mis nooit meer een bericht" + "Oproepen, peilingen, zoekopdrachten en meer zullen later dit jaar worden toegevoegd." + "Berichtgeschiedenis voor versleutelde kamers is nog niet beschikbaar." + "We horen graag van je, laat ons weten wat je ervan vindt via de instellingenpagina." + "Aan de slag!" + "Dit is wat je moet weten:" + "Welkom bij %1$s!" + diff --git a/features/invite/impl/src/main/res/values-nl/translations.xml b/features/invite/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..25eee1572d --- /dev/null +++ b/features/invite/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,9 @@ + + + "Weet je zeker dat je de uitnodiging om toe te treden tot %1$s wilt weigeren?" + "Uitnodiging weigeren" + "Weet je zeker dat je deze privéchat met %1$s wilt weigeren?" + "Chat weigeren" + "Geen uitnodigingen" + "%1$s (%2$s) heeft je uitgenodigd" + diff --git a/features/leaveroom/api/src/main/res/values-nl/translations.xml b/features/leaveroom/api/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..4051ff5274 --- /dev/null +++ b/features/leaveroom/api/src/main/res/values-nl/translations.xml @@ -0,0 +1,6 @@ + + + "Weet je zeker dat je deze kamer wilt verlaten? Je bent de enige persoon hier. Als je weggaat, kan er in de toekomst niemand meer toetreden, ook jij niet." + "Weet je zeker dat je deze kamer wilt verlaten? Deze kamer is niet openbaar en je kunt niet opnieuw deelnemen zonder een uitnodiging." + "Weet je zeker dat je de kamer wilt verlaten?" + diff --git a/features/leaveroom/api/src/main/res/values-zh/translations.xml b/features/leaveroom/api/src/main/res/values-zh/translations.xml index 634c1f045a..9d5f0a5425 100644 --- a/features/leaveroom/api/src/main/res/values-zh/translations.xml +++ b/features/leaveroom/api/src/main/res/values-zh/translations.xml @@ -1,7 +1,7 @@ "您确定要离开此对话吗?此对话不公开,未经邀请您将无法重新加入。" - "你确定要离开这个房间吗?这里只有你一个人,如果你走了,包括你在内的所有人都无法进入此房间。" - "你确定要离开这个房间吗?这个房间不是公开的,如果没有邀请,你将无法重新加入。" - "你确定要离开房间吗?" + "确定要离开这个房间吗?这里只有你一个人。如果你离开此房间,包括你在内的所有人都将无法进入。" + "确定要离开这个房间吗?此房间不公开,没有邀请你将无法重新加入。" + "确定要离开房间吗?" diff --git a/features/lockscreen/impl/src/main/res/values-nl/translations.xml b/features/lockscreen/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..1353f35a74 --- /dev/null +++ b/features/lockscreen/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,4 @@ + + + "Uitloggen…" + diff --git a/features/lockscreen/impl/src/main/res/values-pl/translations.xml b/features/lockscreen/impl/src/main/res/values-pl/translations.xml index 134799b146..7f212e6446 100644 --- a/features/lockscreen/impl/src/main/res/values-pl/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-pl/translations.xml @@ -16,7 +16,7 @@ "Potwierdź PIN" "Zablokuj %1$s, aby zwiększyć bezpieczeństwo swoich czatów. -Wybierz coś łatwego do zapamiętania. Jeśli zapomnisz tego PIN\'u, zostaniesz wylogowany z aplikacji." +Wybierz coś łatwego do zapamiętania. Jeśli zapomnisz ten PIN, zostaniesz wylogowany z aplikacji." "Nie możesz wybrać tego PIN\'u ze względów bezpieczeństwa" "Wybierz inny kod PIN" "Wprowadź ten sam kod PIN dwa razy" diff --git a/features/login/impl/src/main/res/values-de/translations.xml b/features/login/impl/src/main/res/values-de/translations.xml index 398bacb306..2399ec86ba 100644 --- a/features/login/impl/src/main/res/values-de/translations.xml +++ b/features/login/impl/src/main/res/values-de/translations.xml @@ -39,6 +39,20 @@ "Die Verbindung ist nicht sicher" "Du wirst aufgefordert, die beiden unten abgebildeten Ziffern einzugeben." "Trage die unten angezeigte Zahl auf einem anderen Device ein" + "Melde dich auf deinem anderen Gerät an und versuche es dann noch einmal oder verwende ein anderes Gerät, das bereits angemeldet ist." + "Anderes Gerät ist nicht angemeldet" + "Die Anmeldung wurde auf dem anderen Gerät abgebrochen." + "Anmeldeanfrage abgebrochen" + "Die Anmeldung auf dem anderen Gerät wurde abgelehnt." + "Anmelden abgelehnt" + "Die Anmeldung ist abgelaufen. Bitte versuchen Sie es erneut." + "Die Anmeldung wurde nicht rechtzeitig abgeschlossen" + "Dein anderes Gerät unterstützt die Anmeldung bei %s mit einem QR-Code nicht. + +Versuche, dich manuell anzumelden, oder scanne den QR-Code mit einem anderen Gerät." + "QR-Code wird nicht unterstützt" + "Ihr Kontoanbieter unterstützt %1$s nicht." + "%1$swird nicht unterstützt" "Bereit zum Scannen" "%1$s auf einem Desktop-Gerät öffnen" "Klick auf deinen Avatar" diff --git a/features/login/impl/src/main/res/values-nl/translations.xml b/features/login/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..7df748da03 --- /dev/null +++ b/features/login/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,42 @@ + + + "Wijzig accountprovider" + "Homeserver-adres" + "Voer een zoekterm of een domeinnaam in." + "Zoek naar een bedrijf, community of privéserver." + "Vind een accountprovider" + "Dit is waar je gesprekken zullen worden bewaard — net zoals je een e-mailprovider zou gebruiken om je e-mails te bewaren." + "Je staat op het punt om je aan te melden bij %s" + "Dit is waar je gesprekken zullen worden bewaard — net zoals je een e-mailprovider zou gebruiken om je e-mails te bewaren." + "Je staat op het punt een account aan te maken op %s" + "Matrix.org is een grote, gratis server op het openbare Matrix-netwerk voor veilige, gedecentraliseerde communicatie, beheerd door de Matrix.org Foundation." + "Anders" + "Gebruik een andere accountprovider, zoals je eigen privéserver of een zakelijke account." + "Wijzig accountprovider" + "We konden deze homeserver niet bereiken. Controleer of je de homeserver-URL juist hebt ingevoerd. Als de URL juist is, neem dan contact op met de beheerder van je homeserver voor verdere hulp." + "Deze server ondersteunt op dit moment geen sliding sync." + "Homeserver-URL" + "Je kunt alleen verbinding maken met een bestaande server die sliding sync ondersteunt. De beheerder van de homeserver moet dit configureren. %1$s" + "Wat is het adres van je server?" + "Selecteer je server" + "Dit account is gedeactiveerd." + "Onjuiste gebruikersnaam en/of wachtwoord" + "Dit is geen geldige gebruikers-ID. Verwacht formaat: \'@user:homeserver.org\'" + "De geselecteerde homeserver ondersteunt geen wachtwoord of OIDC aanmelding. Neem contact op met je beheerder of kies een andere homeserver." + "Vul je gegevens in" + "Matrix is een open netwerk voor veilige, gedecentraliseerde communicatie." + "Welkom terug!" + "Inloggen bij %1$s" + "Accountprovider wijzigen" + "Een privéserver voor medewerkers van Element." + "Matrix is een open netwerk voor veilige, gedecentraliseerde communicatie." + "Dit is waar je gesprekken zullen worden bewaard — net zoals je een e-mailprovider zou gebruiken om je e-mails te bewaren." + "Je staat op het punt je aan te melden bij %1$s" + "Je staat op het punt een account aan te maken op %1$s" + "Er is momenteel veel vraag naar %1$s op %2$s. Kom over een paar dagen terug naar de app en probeer het opnieuw. + +Bedankt voor je geduld!" + "Welkom bij %1$s!" + "Je bent er bijna." + "Je bent binnen." + diff --git a/features/login/impl/src/main/res/values-zh/translations.xml b/features/login/impl/src/main/res/values-zh/translations.xml index bc5421e42e..0afd6dad93 100644 --- a/features/login/impl/src/main/res/values-zh/translations.xml +++ b/features/login/impl/src/main/res/values-zh/translations.xml @@ -13,12 +13,12 @@ "其他" "使用其他帐户提供者,例如您自己的私人服务器或工作帐户。" "更改账户提供者" - "我们无法访问此主服务器。请检查您输入的主服务器网址是否正确。如果 URL 正确,请联系您的主服务器管理员寻求进一步帮助。" + "我们无法访问此服务器。请检查您输入的服务器网址是否正确。如果 URL 正确,请联系您的服务器管理员寻求进一步帮助。" "由于 Well Known 文件中的问题,Sliding Sync 不可用: %1$s" - "该服务器目前不支持sliding sync。" - "主服务器网址" - "您只能连接到支持sliding sync的现有服务器。您的主服务器管理员需要对其进行配置。%1$s" + "该服务器目前不支持 Sliding Sync。" + "服务器网址" + "您只能连接到支持 Sliding Sync 的现有服务器。您的服务器管理员需要对其进行配置。%1$s" "您的服务器地址是什么?" "选择服务器" "该账户已被停用。" @@ -34,11 +34,13 @@ "无法与新设备建立安全连接。您现有的设备仍然安全,无需担心。" "现在怎么办?" "如果这是网络问题,请尝试使用二维码再次登录" - "如果你遇到同样的问题,请尝试使用不同的 WiFi 网络或使用你的移动数据代替 WiFi" + "如果遇到同样的问题,请尝试使用不同的 WiFi 网络或使用移动数据代替 WiFi" "如果不起作用,请手动登录" "连接不安全" "您会被要求输入此设备上显示的两位数。" "在您的其他设备上输入下面的数字" + "在其他设备登录后重试,或使用另一个已登录的设备。" + "其他设备未登录" "登录被另一台设备取消" "登录请求已取消" "其它设备未接受请求" @@ -74,8 +76,8 @@ "专为 Element 员工提供的私人服务器。" "Matrix 是一个用于安全、去中心化通信的开放网络。" "这是您的对话将进行的地方,就像您使用电子邮件提供商来保存电子邮件一样。" - "你即将登录 %1$s" - "你即将在 %1$s 上创建一个账户" + "即将登录 %1$s" + "即将在 %1$s 上创建一个账户" "目前 %1$s 上 %2$s 的负载很大。过几天再回来试试吧。 感谢您的耐心!" diff --git a/features/logout/impl/src/main/res/values-nl/translations.xml b/features/logout/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..8d7c10d17d --- /dev/null +++ b/features/logout/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,8 @@ + + + "Weet je zeker dat je je wilt uitloggen?" + "Uitloggen" + "Uitloggen" + "Uitloggen…" + "Uitloggen" + diff --git a/features/logout/impl/src/main/res/values-pl/translations.xml b/features/logout/impl/src/main/res/values-pl/translations.xml index ca0d9dc4af..46a5c2d6bd 100644 --- a/features/logout/impl/src/main/res/values-pl/translations.xml +++ b/features/logout/impl/src/main/res/values-pl/translations.xml @@ -1,8 +1,8 @@ "Czy na pewno chcesz się wylogować?" - "Wyloguj się" - "Wyloguj się" + "Wyloguj" + "Wyloguj" "Wylogowywanie…" "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." "Wyłączyłeś backup" @@ -10,7 +10,7 @@ "Twoje klucze są nadal archiwizowane" "Zanim się wylogujesz, poczekaj na zakończenie operacji." "Twoje klucze są nadal archiwizowane" - "Wyloguj się" + "Wyloguj" "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." "Nie ustawiono przywracania" "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." diff --git a/features/logout/impl/src/main/res/values-zh/translations.xml b/features/logout/impl/src/main/res/values-zh/translations.xml index be1d740130..0a8ec07e87 100644 --- a/features/logout/impl/src/main/res/values-zh/translations.xml +++ b/features/logout/impl/src/main/res/values-zh/translations.xml @@ -4,15 +4,15 @@ "登出" "登出" "正在登出…" - "您即将登出最后一个会话。如果现在登出,你将无法访问加密的消息。" + "即将登出最后一个会话。如果现在登出,将无法访问加密的消息。" "您已关闭备份" - "当你离线时,你的密钥仍在备份中。重新连接,以便在登出之前备份密钥。" + "当你离线时,密钥仍在备份中。重新连接以便在登出之前备份密钥。" "您的密钥仍在备份中" "请等待此操作完成后再登出。" "您的密钥仍在备份中" "登出" - "您即将登出最后一个会话。如果现在登出,你将无法访问加密的消息。" + "即将登出最后一个会话。如果现在登出,将无法访问加密的消息。" "未设置恢复" - "您即将登出最后一个会话。如果现在登出,你将无法访问加密的消息。" + "即将登出最后一个会话。如果现在登出,将无法访问加密的消息。" "您保存了恢复密钥吗?" diff --git a/features/messages/impl/src/main/res/values-nl/translations.xml b/features/messages/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..87bbe0e7a7 --- /dev/null +++ b/features/messages/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,42 @@ + + + "Activiteiten" + "Vlaggen" + "Eten & Drinken" + "Dieren & Natuur" + "Voorwerpen" + "Smileys & Mensen" + "Reizen & Locaties" + "Symbolen" + "Gebruiker blokkeren" + "Vink aan als je alle huidige en toekomstige berichten van deze gebruiker wilt verbergen" + "Dit bericht wordt gerapporteerd aan de beheerder van je homeserver. Ze zullen geen versleutelde berichten kunnen lezen." + "Reden voor het melden van deze inhoud" + "Camera" + "Foto maken" + "Video opnemen" + "Bijlage" + "Foto & Video Bibliotheek" + "Locatie" + "Peiling" + "Tekstopmaak" + "Berichtgeschiedenis is momenteel niet beschikbaar." + "Wil je ze terug uitnodigen?" + "Je bent alleen in deze chat" + "Iedereen" + "Opnieuw verzenden" + "Je bericht is niet verzonden" + "Emoji toevoegen" + "Dit is het begin van %1$s." + "Dit is het begin van dit gesprek." + "Toon minder" + "Bericht gekopieerd" + "Je hebt geen toestemming om berichten in deze kamer te plaatsen" + "Minder tonen" + "Meer tonen" + "Nieuw" + + "%1$d kamerverandering" + "%1$d kamerveranderingen" + + diff --git a/features/messages/impl/src/main/res/values-pl/translations.xml b/features/messages/impl/src/main/res/values-pl/translations.xml index add70eb71d..c1ffb49d2c 100644 --- a/features/messages/impl/src/main/res/values-pl/translations.xml +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -48,9 +48,9 @@ "%1$s, %2$s i %3$d innych" - "%1$s piszę" + "%1$s pisze" "%1$s piszą" - "%1$s pisze" + "%1$s piszą" "%1$s i %2$s" diff --git a/features/messages/impl/src/main/res/values-zh/translations.xml b/features/messages/impl/src/main/res/values-zh/translations.xml index 8e2e049453..6276eb5959 100644 --- a/features/messages/impl/src/main/res/values-zh/translations.xml +++ b/features/messages/impl/src/main/res/values-zh/translations.xml @@ -10,7 +10,7 @@ "符号" "封禁用户" "请确认是否要隐藏该用户当前和未来的所有信息" - "此消息将举报给您的主服务器管理员。他们无法读取任何加密消息。" + "此消息将举报给您的服务器管理员。他们无法读取任何加密消息。" "举报此内容的原因" "相机" "拍摄照片" @@ -26,7 +26,7 @@ "聊天中只有你一个人" "通知整个房间" "所有人" - "重新发送" + "再次发送" "消息发送失败" "添加表情符号" "这是 %1$s 聊天室的开始。" diff --git a/features/onboarding/impl/src/main/res/values-nl/translations.xml b/features/onboarding/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..86bbf73ade --- /dev/null +++ b/features/onboarding/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,9 @@ + + + "Handmatig inloggen" + "Inloggen met QR-code" + "Account aanmaken" + "Welkom bij de snelste %1$s ooit. Supercharged, voor snelheid en eenvoud." + "Welkom bij %1$s. Supercharged, voor snelheid en eenvoud." + "Wees in je element" + diff --git a/features/poll/impl/src/main/res/values-nl/translations.xml b/features/poll/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..b3c0ae1f78 --- /dev/null +++ b/features/poll/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,11 @@ + + + "Optie toevoegen" + "Resultaten pas weergeven nadat de peiling is afgelopen" + "Stemmen verbergen" + "Optie %1$d" + "Vraag of onderwerp" + "Waar gaat de peiling over?" + "Peiling maken" + "Peiling wijzigen" + diff --git a/features/preferences/impl/src/main/res/values-de/translations.xml b/features/preferences/impl/src/main/res/values-de/translations.xml index 3013315b21..01f0749846 100644 --- a/features/preferences/impl/src/main/res/values-de/translations.xml +++ b/features/preferences/impl/src/main/res/values-de/translations.xml @@ -1,11 +1,14 @@ + "Damit du keinen wichtigen Anruf verpasst, ändere bitte deine Einstellungen so, dass du bei gesperrtem Telefon Benachrichtigungen im Vollbildmodus erhältst." + "Verbessere dein Anruferlebnis" "Wähle aus, wie du Benachrichtigungen erhalten möchtest" "Entwickler-Modus" "Aktivieren, um Zugriff auf Features und Funktionen für Entwickler zu aktivieren." "Benutzerdefinierte Element-Aufruf-Basis-URL" "Lege eine eigene Basis-URL für Element Call fest." "Ungültige URL, bitte stelle sicher, dass du das Protokoll (http/https) und die richtige Adresse angibst." + "Anbieter für Push-Benachrichtigungen" "Deaktiviere den Rich-Text-Editor, um Markdown manuell einzugeben." "Lesebestätigungen" "Wenn diese Option deaktiviert ist, werden Ihre Lesebestätigungen an niemanden gesendet. Du erhältst weiterhin Lesebestätigungen von anderen Benutzern." diff --git a/features/preferences/impl/src/main/res/values-nl/translations.xml b/features/preferences/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..2e4497718d --- /dev/null +++ b/features/preferences/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,41 @@ + + + "Kies hoe je meldingen wilt ontvangen" + "Ontwikkelaarsmodus" + "Schakel in om toegang te krijgen tot tools en functies voor ontwikkelaars." + "Schakel de uitgebreide tekstverwerker uit om Markdown handmatig te typen." + "Deblokkeren" + "Je zult alle berichten van hen weer kunnen zien." + "Gebruiker deblokkeren" + "Weergavenaam" + "Je weergavenaam" + "Er is een onbekende fout opgetreden en de informatie kon niet worden gewijzigd." + "Kan profiel niet bijwerken" + "Profiel bewerken" + "Profiel bijwerken…" + "Aanvullende instellingen" + "Audio- en videogesprekken" + "Configuratie komt niet overeen" + "We hebben de instellingen voor meldingen vereenvoudigd, zodat je de opties gemakkelijker kunt vinden. Sommige instellingen die je in het verleden hebt aangepast, worden hier niet getoond, maar zijn nog steeds actief. + +Als je doorgaat, kunnen sommige van je instellingen veranderen." + "Directe chats" + "Aangepaste instelling per chat" + "Er is een fout opgetreden bij het bijwerken van de meldingsinstelling." + "Alle berichten" + "Alleen vermeldingen en trefwoorden" + "Bij directe chats, stuur me een melding voor" + "Bij groep chats, stuur me een melding voor" + "Meldingen op dit apparaat inschakelen" + "De configuratie is niet gecorrigeerd. Probeer het opnieuw." + "Groep chats" + "Vermeldingen" + "Alles" + "Vermeldingen" + "Stuur me een melding voor" + "Stuur me een melding bij @kamer" + "Wijzig je %1$s om meldingen te ontvangen." + "systeeminstellingen" + "Systeemmeldingen uitgeschakeld" + "Meldingen" + diff --git a/features/preferences/impl/src/main/res/values-zh/translations.xml b/features/preferences/impl/src/main/res/values-zh/translations.xml index 13e52fdcda..6e74db47c2 100644 --- a/features/preferences/impl/src/main/res/values-zh/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh/translations.xml @@ -1,9 +1,11 @@ + "为确保您不会错过重要来电,请更改设置以允许锁屏时的全屏通知。" + "提升通话体验" "选择如何接收通知" "开发者模式" "允许开发人员访问特性和功能。" - "自定义 Element 通话 URL" + "自定义 Element Call URL" "为 Element 通话设置根 URL。" "URL 无效,请确保包含协议(http/https)和正确的地址。" "通知推送提供者" @@ -12,10 +14,10 @@ "如果关闭,您的已读回执将不会发送给别人。您仍能收到别人的已读回执。" "分享在线状态" "如果关闭,您将无法发送或接收已读回执、输入通知" - "启用在时间轴中查看消息来源的选项。" + "启用在时间轴中查看消息源码的选项。" "您没有屏蔽用户" "解封" - "你可以重新接收他们的消息。" + "可以重新接收他们的消息。" "解封用户" "正在解除屏蔽……" "显示名称" diff --git a/features/rageshake/api/src/main/res/values-nl/translations.xml b/features/rageshake/api/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..a6d1d2e369 --- /dev/null +++ b/features/rageshake/api/src/main/res/values-nl/translations.xml @@ -0,0 +1,7 @@ + + + "%1$s crashte de laatste keer dat het werd gebruikt. Wil je een crashrapport met ons delen?" + "Het lijkt erop dat je gefrustreerd de telefoon hebt geschud. Wil je het scherm openen om een bug te rapporteren?" + "Schudden uit woede" + "Drempel voor detectie" + diff --git a/features/rageshake/api/src/main/res/values-zh/translations.xml b/features/rageshake/api/src/main/res/values-zh/translations.xml index 38942e2f1a..34a643ceab 100644 --- a/features/rageshake/api/src/main/res/values-zh/translations.xml +++ b/features/rageshake/api/src/main/res/values-zh/translations.xml @@ -1,6 +1,6 @@ - "%1$s 上次使用时崩溃了。你想和我们分享崩溃报告吗?" + "%1$s 上次使用时崩溃了。想和我们分享崩溃报告吗?" "你似乎愤怒地摇晃了手机。想要打开 Bug 报告页面吗?" "摇一摇" "检测阈值" diff --git a/features/rageshake/impl/src/main/res/values-nl/translations.xml b/features/rageshake/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..771c95fc6e --- /dev/null +++ b/features/rageshake/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,15 @@ + + + "Schermafbeelding bijvoegen" + "Je mag contact met mij opnemen als je nog vervolg vragen hebt." + "Neem contact met mij op" + "Schermafbeelding bewerken" + "Beschrijf het probleem. Wat heb je gedaan? Wat had je verwacht? Wat is er daadwerkelijk gebeurd. Beschrijf het zo gedetailleerd mogelijk." + "Beschrijf het probleem…" + "Geeft de beschrijving in het Engels indien mogelijk." + "Crashlogboeken verzenden" + "Logboeken toestaan" + "Schermafbeelding verzenden" + "Er worden logbestanden bij uw bericht gevoegd om er zeker van te zijn dat alles goed werkt. Als u uw bericht zonder logbestanden wilt verzenden, schakelt u deze instelling uit." + "%1$s crashte de laatste keer dat het werd gebruikt. Wil je een crashrapport met ons delen?" + diff --git a/features/rageshake/impl/src/main/res/values-pl/translations.xml b/features/rageshake/impl/src/main/res/values-pl/translations.xml index 21e8ad69c6..36b86289b2 100644 --- a/features/rageshake/impl/src/main/res/values-pl/translations.xml +++ b/features/rageshake/impl/src/main/res/values-pl/translations.xml @@ -1,8 +1,8 @@ "Załącz zrzut ekranu" - "Możecie skontaktować się ze mną, jeśli macie jakiekolwiek dodatkowe pytania." - "Napisz do mnie" + "Zezwól na kontakt ze mną, jeśli są jakiekolwiek dodatkowe pytania." + "Kontakt ze mną" "Edytuj zrzut ekranu" "Opisz problem. Co zrobiłeś? Czego oczekiwałeś? Co się stało zamiast tego. Podaj jak najwięcej szczegółów." "Opisz problem…" diff --git a/features/rageshake/impl/src/main/res/values-zh/translations.xml b/features/rageshake/impl/src/main/res/values-zh/translations.xml index 7fbf6bd644..59da17e82d 100644 --- a/features/rageshake/impl/src/main/res/values-zh/translations.xml +++ b/features/rageshake/impl/src/main/res/values-zh/translations.xml @@ -12,6 +12,6 @@ "允许日志" "发送屏幕截图" "为确认一切正常运行,您的消息中将包含日志。如要发送不带日志的消息,请关闭此设置。" - "%1$s 上次使用时崩溃了。你想和我们分享崩溃报告吗?" + "%1$s 上次使用时崩溃了。想和我们分享崩溃报告吗?" "查看日志" diff --git a/features/roomdetails/impl/src/main/res/values-nl/translations.xml b/features/roomdetails/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..f3b274ae0c --- /dev/null +++ b/features/roomdetails/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,45 @@ + + + "Er is een fout opgetreden bij het bijwerken van de meldingsinstelling." + "Iedereen" + "Onderwerp toevoegen" + "Reeds lid" + "Reeds uitgenodigd" + "Kamer bewerken" + "Er is een onbekende fout opgetreden en de informatie kon niet worden gewijzigd." + "Kan kamer niet bijwerken" + "Berichten zijn beveiligd met sloten. Alleen jij en de ontvangers hebben de unieke sleutels om ze te ontgrendelen." + "Berichtversleuteling ingeschakeld" + "Er is een fout opgetreden bij het laden van de meldingsinstellingen." + "Het dempen van deze kamer is mislukt. Probeer het opnieuw." + "Het dempen opheffen voor deze kamer is mislukt. Probeer het opnieuw." + "Mensen uitnodigen" + "Ruimte verlaten" + "Aangepast" + "Standaard" + "Meldingen" + "Naam van de kamer" + "Beveiliging" + "Kamer delen" + "Onderwerp" + "Kamer bijwerken…" + + "%1$d persoon" + "%1$d personen" + + "In behandeling" + "Kamerleden" + "Aanpassen toestaan" + "Als je dit inschakelt, wordt je standaardinstelling overschreven" + "Stuur me een melding in deze chat voor" + "Je kunt het wijzigen in je %1$s." + "algemene instellingen" + "Standaardinstelling" + "Aanpassingen verwijderen" + "Er is een fout opgetreden bij het laden van de meldingsinstellingen." + "Het herstellen van de standaardmeldingen is mislukt. Probeer het opnieuw." + "Het instellen van de meldingen is mislukt. Probeer het opnieuw." + "Alle berichten" + "Alleen vermeldingen en trefwoorden" + "In deze kamer, stuur me een melding voor" + diff --git a/features/roomdetails/impl/src/main/res/values-zh/translations.xml b/features/roomdetails/impl/src/main/res/values-zh/translations.xml index c6cf9890b3..660021d604 100644 --- a/features/roomdetails/impl/src/main/res/values-zh/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh/translations.xml @@ -41,7 +41,7 @@ "编辑聊天室" "出现未知错误,无法更改信息。" "无法更新聊天室" - "你的消息受加密保护,并且只有你和消息接收者拥有唯一解密密钥。" + "消息已加密,只有你和消息接收者拥有唯一解密密钥。" "消息加密已启用" "加载通知设置时出错。" "无法将此房间静音,请重试。" diff --git a/features/roomlist/impl/src/main/res/values-de/translations.xml b/features/roomlist/impl/src/main/res/values-de/translations.xml index 36442d6f7e..6215b3d4e4 100644 --- a/features/roomlist/impl/src/main/res/values-de/translations.xml +++ b/features/roomlist/impl/src/main/res/values-de/translations.xml @@ -2,6 +2,8 @@ "Dein Chat-Backup ist derzeit nicht synchronisiert. Du musst deinen Wiederherstellungsschlüssel bestätigen, um Zugriff auf dein Chat-Backup zu erhalten." "Wiederherstellungsschlüssel bestätigen." + "Damit du keinen wichtigen Anruf verpasst, ändere bitte deine Einstellungen so, dass du bei gesperrtem Telefon Benachrichtigungen im Vollbildmodus erhältst." + "Verbessere dein Anruferlebnis" "Möchtest du die Einladung zum Betreten von %1$s wirklich ablehnen?" "Einladung ablehnen" "Bist du sicher, dass du diese Direktnachricht von %1$s ablehnen möchtest?" diff --git a/features/roomlist/impl/src/main/res/values-nl/translations.xml b/features/roomlist/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..df2a4ce410 --- /dev/null +++ b/features/roomlist/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,18 @@ + + + "Weet je zeker dat je de uitnodiging om toe te treden tot %1$s wilt weigeren?" + "Uitnodiging weigeren" + "Weet je zeker dat je deze privéchat met %1$s wilt weigeren?" + "Chat weigeren" + "Geen uitnodigingen" + "%1$s (%2$s) heeft je uitgenodigd" + "Dit is een eenmalig proces, bedankt voor het wachten." + "Je account instellen." + "Begin een nieuw gesprek of maak een nieuwe kamer" + "Ga aan de slag door iemand een bericht te sturen." + "Nog geen chats." + "Personen" + "Chats" + "Het lijkt erop dat je een nieuw apparaat gebruikt. Verifieer met een ander apparaat om toegang te krijgen tot je versleutelde berichten." + "Verifieer dat jij het bent" + diff --git a/features/roomlist/impl/src/main/res/values-zh/translations.xml b/features/roomlist/impl/src/main/res/values-zh/translations.xml index 053de06f1a..b77275bb8d 100644 --- a/features/roomlist/impl/src/main/res/values-zh/translations.xml +++ b/features/roomlist/impl/src/main/res/values-zh/translations.xml @@ -1,7 +1,9 @@ - "您的聊天备份当前不同步。您需要输入恢复密钥才能访问聊天备份。" - "输入您的恢复密钥" + "聊天备份目前不同步,需要输入恢复密钥才能访问聊天备份。" + "输入恢复密钥" + "为确保您不会错过重要来电,请更改设置以允许锁屏时的全屏通知。" + "提升通话体验" "您确定要拒绝加入 %1$s 的邀请吗?" "拒绝邀请" "您确定要拒绝与 %1$s 开始私聊吗?" @@ -14,11 +16,11 @@ "通过向某人发送消息来开始。" "还没有聊天。" "收藏夹" - "您可以在聊天设置中将聊天添加到收藏夹中。 -现在,你可以取消选择过滤器以查看你的其他对话。" + "可以在聊天设置里将聊天添加到收藏夹中。 +现在,可以取消选择过滤器以查看其他对话。" "您未收藏任何聊天" "邀请" - "你没有任何待处理的邀请。" + "没有待处理的邀请。" "低优先级" "您可以取消选择过滤器以查看其他对话" "您没有关于此选项的聊天" @@ -28,7 +30,7 @@ "您尚未进入任何聊天室" "未读" "恭喜! -你没有任何未读消息!" +没有任何未读消息!" "全部聊天" "标记为已读" "标记为未读" diff --git a/features/securebackup/impl/src/main/res/values-be/translations.xml b/features/securebackup/impl/src/main/res/values-be/translations.xml index b4a71d766f..db237bbe19 100644 --- a/features/securebackup/impl/src/main/res/values-be/translations.xml +++ b/features/securebackup/impl/src/main/res/values-be/translations.xml @@ -16,6 +16,12 @@ "Выконвайце інструкцыі, каб стварыць новы ключ аднаўлення" "Захавайце новы ключ аднаўлення ў ме́неджэры пароляў або ў зашыфраванай нататке" "Скіньце шыфраванне для вашага ўліковага запісу з дапамогай іншай прылады" + "Дадзеныя вашага ўліковага запісу, кантакты, налады і спіс чатаў будуць захаваны" + "Вы страціце існуючую гісторыю паведамленняў" + "Вам трэба будзе зноў запэўніць ўсе вашы існуючыя прылады і кантакты" + "Працягвайце, толькі калі вы ўпэўненыя, што страцілі ўсе астатнія прылады і ключ аднаўлення." + "Калі вы не ўвайшлі ў сістэму на іншых прыладах і страцілі ключ аднаўлення, вам неабходна скінуць ключы пацверджання, каб працягнуць выкарыстанне прыкладання." + "Скіньце ключы пацверджання, калі вы не можаце пацвердзіць яго іншым спосабам" "Адключыць" "Вы страціце зашыфраваныя паведамленні, калі выйдзеце з усіх прылад." "Вы ўпэўнены, што хочаце адключыць рэзервовае капіраванне?" @@ -51,4 +57,11 @@ "Пераканайцеся, што вы можаце захаваць ключ аднаўлення ў бяспечным месцы" "Наладка аднаўлення прайшла паспяхова" "Наладзьце аднаўленне" + "Так, скінуць зараз" + "Гэты працэс незваротны." + "Вы ўпэўнены, што хочаце скінуць шыфраванне?" + "Адбылася невядомая памылка. Калі ласка, праверце правільнасць пароля вашага ўліковага запісу і паўтарыце спробу." + "Увод…" + "Пацвердзіце, што вы хочаце скінуць шыфраванне" + "Каб працягнуць, увядзіце пароль уліковага запісу" diff --git a/features/securebackup/impl/src/main/res/values-cs/translations.xml b/features/securebackup/impl/src/main/res/values-cs/translations.xml index 18255155d2..442fa42630 100644 --- a/features/securebackup/impl/src/main/res/values-cs/translations.xml +++ b/features/securebackup/impl/src/main/res/values-cs/translations.xml @@ -16,6 +16,12 @@ "Postupujte podle pokynů k vytvoření nového obnovovacího klíče" "Uložte nový klíč pro obnovení do správce hesel nebo do zašifrované poznámky" "Obnovte šifrování účtu pomocí jiného zařízení" + "Podrobnosti o vašem účtu, kontaktech, preferencích a seznamu chatu budou zachovány" + "Ztratíte svou stávající historii zpráv" + "Budete muset znovu ověřit všechna stávající zařízení a kontakty" + "Obnovte svou identitu pouze v případě, že nemáte přístup k jinému přihlášenému zařízení a ztratili jste klíč pro obnovení." + "Pokud nejste přihlášeni k žádnému jinému zařízení a ztratili jste klíč pro obnovení, budete muset obnovit svou identitu, abyste mohli pokračovat v používání aplikace. " + "Obnovte svou identitu v případě, že nemůžete potvrdit jiným způsobem" "Vypnout" "Pokud se odhlásíte ze všech zařízení, přijdete o zašifrované zprávy." "Opravdu chcete vypnout zálohování?" @@ -51,4 +57,11 @@ "Ujistěte se, že můžete klíč pro obnovení uložit někde v bezpečí" "Nastavení obnovení bylo úspěšné" "Nastavení obnovy" + "Ano, resetovat nyní" + "Tento proces je nevratný." + "Opravdu chcete obnovit šifrování?" + "Došlo k neznámé chybě. Zkontrolujte, zda je heslo k účtu správné a zkuste to znovu." + "Zadat…" + "Potvrďte, že chcete obnovit šifrování." + "Pro pokračování zadejte heslo k účtu" diff --git a/features/securebackup/impl/src/main/res/values-et/translations.xml b/features/securebackup/impl/src/main/res/values-et/translations.xml index 00efa8cf14..cec56f5789 100644 --- a/features/securebackup/impl/src/main/res/values-et/translations.xml +++ b/features/securebackup/impl/src/main/res/values-et/translations.xml @@ -16,6 +16,12 @@ "Uue taastevõtme loomiseks palun järgi juhendit" "Salvesta oma uus taastevõti kas salasõnahalduris, krüptitud failis või mõnel muul turvalisel viisil" "Lähtesta oma konto krüptimine mõnest muust oma seadmest" + "Sinu kasutajakonto andmed, kontaktid, eelistused ja vestluste loend säiluvad" + "Sa kaotad seniste sõnumite ajaloo" + "Sa pead kõik oma olemasolevad seadmed ja kontaktid uuesti verifitseerima" + "Lähtesta oma identiteet vaid siis, kui sul pole ligipääsu mitte ühelegi oma seadmele ja sa oled kaotanud oma taastevõtme." + "Kui sa soovid jätkata selle rakenduse kasutamist ja sa pole mitte üheski seadmes sisse logitud ning oled kaotanud oma taastevõtme, siis tõesti pead lähtestama oma identiteedi. " + "Kui sa ühtegi muud võimalust ei leia, siis lähtesta oma identiteet." "Lülita välja" "Kui sa logid välja kõikidest oma seadmetest, siis sa kaotad ligipääsu oma krüptitud sõnumitele." "Kas sa oled kindel, et soovid varukoopiate tegemise välja lülitada?" @@ -51,4 +57,11 @@ "Palun hoia taastevõtit turvaliselt, näiteks vana kooli seifis või digitaalses salasõnalaekas" "Andmete taastamise seadistamine õnnestus" "Seadista andmete taastamine" + "Jah, lähtesta nüüd" + "See tegevus on tagasipöördumatu." + "Kas sa oled kindel, et soovid oma andmete krüptimist lähtestada?" + "Tekkis teadmata viga. Palun kontrolli, kas sinu kasutajakonto salasõna on õige ja proovi uuesti." + "Sisesta…" + "Palun kinnita, et soovid oma andmete krüptimist lähtestada." + "Jätkamaks sisesta oma kasutajakonto salasõna" diff --git a/features/securebackup/impl/src/main/res/values-fr/translations.xml b/features/securebackup/impl/src/main/res/values-fr/translations.xml index a23f66f643..68d6ac2e19 100644 --- a/features/securebackup/impl/src/main/res/values-fr/translations.xml +++ b/features/securebackup/impl/src/main/res/values-fr/translations.xml @@ -16,6 +16,9 @@ "Suivez les instructions pour créer une nouvelle clé de récupération" "Enregistrez votre nouvelle clé dans un gestionnaire de mots de passe ou dans une note chiffrée" "Réinitialisez le chiffrement de votre compte en utilisant un autre appareil" + "Les détails de votre compte, vos contacts, vos préférences et votre liste de discussions seront conservés" + "Vous perdrez l’historique de vos messages" + "Vous devrez vérifier à nouveau tous vos appareils et tous vos contacts" "Désactiver" "Vous perdrez vos messages chiffrés si vous vous déconnectez de toutes vos sessions." "Êtes-vous certain de vouloir désactiver la sauvegarde?" @@ -51,4 +54,8 @@ "Assurez-vous de conserver la clé dans un endroit sûr" "Sauvegarde mise en place avec succès" "Configurer la sauvegarde" + "Oui, réinitialisez maintenant" + "Cette opération ne peut pas être annulée." + "Saisissez…" + "Saisissez le mot de passe de votre compte pour continuer" diff --git a/features/securebackup/impl/src/main/res/values-hu/translations.xml b/features/securebackup/impl/src/main/res/values-hu/translations.xml index 68db567a89..6def2d41cd 100644 --- a/features/securebackup/impl/src/main/res/values-hu/translations.xml +++ b/features/securebackup/impl/src/main/res/values-hu/translations.xml @@ -16,6 +16,12 @@ "Kövesse az utasításokat egy új helyreállítási kulcs létrehozásához" "Mentse az új helyreállítási kulcsot egy jelszókezelőbe vagy egy titkosított jegyzetbe." "A fiók titkosításának visszaállítása egy másik eszköz használatával" + "A fiókadatok, a kapcsolatok, a beállítások és a csevegéslista megmarad" + "Elveszíti meglévő üzenetelőzményeit" + "Újból ellenőriznie kell az összes meglévő eszközét és csevegőpartnerét" + "Csak akkor állítsa vissza a személyazonosságát, ha nem fér hozzá másik bejelentkezett eszközhöz, és elvesztette a helyreállítási kulcsot." + "Ha nincs bejelentkezve más eszközre, és elvesztette a helyreállítási kulcsot, akkor az alkalmazás használatának folytatásához vissza kell állítania személyazonosságát. " + "Állítsa vissza a személyazonosságát, ha más módon nem tudja megerősíteni" "Kikapcsolás" "Ha kijelentkezik az összes eszközéről, akkor elveszti a titkosított üzeneteit." "Biztos, hogy kikapcsolja a biztonsági mentéseket?" @@ -51,4 +57,10 @@ "Gondoskodjon arról, hogy biztonságos helyen tárolja a helyreállítási kulcsát" "A helyreállítás beállítása sikeres" "Helyreállítás beállítása" + "Igen, visszaállítás most" + "Ez a folyamat visszafordíthatatlan." + "Biztos, hogy visszaállítja a titkosítást?" + "Adja meg…" + "Erősítse meg, hogy vissza szeretné állítani a titkosítást." + "A folytatáshoz adja meg fiókja jelszavát" diff --git a/features/securebackup/impl/src/main/res/values-it/translations.xml b/features/securebackup/impl/src/main/res/values-it/translations.xml index 7b2a40341a..cbeadcc2e1 100644 --- a/features/securebackup/impl/src/main/res/values-it/translations.xml +++ b/features/securebackup/impl/src/main/res/values-it/translations.xml @@ -16,6 +16,12 @@ "Segui le istruzioni per creare una nuova chiave di recupero" "Salva la tua nuova chiave di recupero in un gestore di password o in una nota cifrata." "Reimposta la crittografia del tuo account utilizzando un altro dispositivo" + "I dettagli del tuo account, i contatti, le preferenze e l\'elenco delle conversazioni verranno conservati" + "Perderai la cronologia dei messaggi esistente" + "Dovrai verificare nuovamente tutti i dispositivi e i contatti esistenti" + "Reimposta la tua identità solo se non hai accesso a un altro dispositivo su cui hai effettuato l\'accesso e hai perso la chiave di recupero." + "Se non hai effettuato l\'accesso su nessun altro dispositivo e hai perso la chiave di recupero, dovrai reimpostare la tua identità per continuare a utilizzare l\'app." + "Reimposta la tua identità nel caso in cui non riesci a confermare in un altro modo" "Disattiva" "Perderai i tuoi messaggi cifrati se sei disconnesso da tutti i dispositivi." "Vuoi davvero disattivare il backup?" @@ -51,4 +57,10 @@ "Assicurati di conservare la chiave di recupero in un posto sicuro" "Configurazione del recupero completata" "Configura il recupero" + "Sì, reimposta ora" + "Questo processo è irreversibile." + "Sei sicuro di voler reimpostare la crittografia?" + "Inserisci…" + "Conferma di voler reimpostare la crittografia." + "Inserisci la password del tuo account per continuare" diff --git a/features/securebackup/impl/src/main/res/values-nl/translations.xml b/features/securebackup/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..80460745ca --- /dev/null +++ b/features/securebackup/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,13 @@ + + + "Back-up uitschakelen" + "Back-up inschakelen" + "Een back-up maken zorgt ervoor dat je je berichtgeschiedenis niet verliest. %1$s." + "Back-up" + "Wijzig recovery key" + "Voer recovery key in" + "Je chatback-up is momenteel niet gesynchroniseerd." + "Herstelmogelijkheid instellen" + "Krijg toegang tot je versleutelde berichten als je al je apparaten kwijtraakt of overal uit %1$s bent uitgelogd." + "Weet je zeker dat je de back-up wilt uitschakelen?" + diff --git a/features/securebackup/impl/src/main/res/values-pl/translations.xml b/features/securebackup/impl/src/main/res/values-pl/translations.xml index 17a4c1a4db..749fea102a 100644 --- a/features/securebackup/impl/src/main/res/values-pl/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pl/translations.xml @@ -16,6 +16,12 @@ "Postępuj zgodnie z instrukcjami, aby utworzyć nowy klucz przywracania" "Zapisz nowy klucz przywracania w menedżerze haseł lub notatce szyfrowanej" "Resetuj szyfrowanie swojego konta za pomocą drugiego urządzenia" + "Szczegóły konta, kontakty, preferencje i lista czatów zostaną zachowane" + "Utracisz istniejącą historię wiadomości" + "Wymagana będzie ponowna weryfikacja istniejących urządzeń i kontaktów" + "Zresetuj swoją tożsamość tylko wtedy, gdy nie jesteś zalogowany na żadnym urządzeniu i straciłeś swój klucz przywracania." + "Jeśli nie jesteś zalogowany na żadnym innym urządzeniu i straciłeś swój klucz przywracania, musisz zresetować swoją tożsamość, aby kontynuować korzystanie z aplikacji. " + "Zresetuj swoją tożsamość, jeśli nie możesz jej potwierdzić w inny sposób" "Wyłącz" "Jeśli wylogujesz się ze wszystkich urządzeń, stracisz wszystkie wiadomości szyfrowane." "Czy na pewno chcesz wyłączyć backup?" @@ -51,4 +57,10 @@ "Upewnij się, że klucz przywracania możesz przechowywać w bezpiecznym miejscu" "Skonfigurowano przywracanie pomyślnie" "Skonfiguruj przywracanie" + "Tak, zresetuj teraz" + "Tego procesu nie można odwrócić." + "Czy na pewno chcesz zresetować szyfrowanie?" + "Wprowadź…" + "Potwierdź, że chcesz zresetować szyfrowanie." + "Wprowadź hasło, aby kontynuować" diff --git a/features/securebackup/impl/src/main/res/values-pt/translations.xml b/features/securebackup/impl/src/main/res/values-pt/translations.xml index 0d8d61137c..27d41c98c2 100644 --- a/features/securebackup/impl/src/main/res/values-pt/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pt/translations.xml @@ -16,6 +16,12 @@ "Segue as instruções para criar uma nova chave de recuperação" "Guarda a tua nova chave de recuperação num gestor de senhas ou numa nota cifrada" "Repor a cifragem da tua conta utilizando outro dispositivo" + "Os detalhes da tua conta, contactos, preferências e lista de conversas serão mantidos." + "Perderás o acesso ao teu histórico de mensagens existente" + "Necessitarás de verificar todos os teus dispositivos e contactos novamente." + "Repõe a tua identidade apenas se não tiveres acesso a mais nenhum dispositivo com sessão iniciada e se tiveres perdido a tua chave de recuperação." + "Se não tiveres sessão iniciada em nenhum outro dispositivo e perdeste o acesso à tua chave de recuperação, precisarás de repor a tua identidade para continuares a usar a aplicação. " + "Repõe a tua identidade caso não consigas confirmar de outra forma" "Desligar" "Perderás as tuas mensagens cifradas se tiveres terminado a sessão em todos os teus dispositivos." "Tens a certeza que queres desativar a cópia de segurança?" @@ -51,4 +57,10 @@ "Certifica-te de que podes guardar a tua chave de recuperação num local seguro" "Recuperação configurada com sucesso" "Configurar recuperação" + "Sim, repor agora" + "Este processo é irreversível." + "Tens a certeza que pretendes repor a tua cifra?" + "Inserir…" + "Confirma que pretendes realmente repor a tua cifra." + "Insere a tua palavra-passe para continuares" diff --git a/features/securebackup/impl/src/main/res/values-ru/translations.xml b/features/securebackup/impl/src/main/res/values-ru/translations.xml index 23de19d911..c02d05952d 100644 --- a/features/securebackup/impl/src/main/res/values-ru/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ru/translations.xml @@ -26,6 +26,12 @@ " в менеджере паролей или зашифрованной заметке" "Сбросьте шифрование вашей учетной записи с помощью другого устройства." + "Данные вашей учетной записи, контакты, настройки и список чатов будут сохранены" + "Вы потеряете существующую историю сообщений" + "Вам нужно будет заново подтвердить все существующие устройства и контакты." + "Сбрасывайте данные только в том случае, если у вас нет доступа к другому устройству, на котором выполнен вход, и вы потеряли ключ восстановления." + "Если вы не вошли в систему на других устройствах и потеряли ключ восстановления, вам необходимо сбросить учетные данные, чтобы продолжить использование приложения. " + "Сбросьте ключи подтверждения, если вы не можете подтвердить свою личность другим способом." "Выключить" "Вы потеряете зашифрованные сообщения, если выйдете из всех устройств." "Вы действительно хотите отключить резервное копирование?" @@ -94,4 +100,11 @@ "Убедитесь, что вы можете хранить ключ восстановления в безопасном месте" "Настройка восстановления выполнена успешно" "Настроить восстановление" + "Да, сбросить сейчас" + "Этот процесс необратим." + "Вы действительно хотите сбросить шифрование?" + "Произошла неизвестная ошибка. Проверьте правильность пароля учетной записи и повторите попытку." + "Ввод…" + "Подтвердите, что вы хотите сбросить шифрование." + "Введите пароль своей учетной записи, чтобы продолжить" diff --git a/features/securebackup/impl/src/main/res/values-sk/translations.xml b/features/securebackup/impl/src/main/res/values-sk/translations.xml index 64ec3c7fac..7d15dd352a 100644 --- a/features/securebackup/impl/src/main/res/values-sk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-sk/translations.xml @@ -16,6 +16,12 @@ "Postupujte podľa pokynov na vytvorenie nového kľúča na obnovenie" "Uložte si nový kľúč na obnovenie do správcu hesiel alebo do zašifrovanej poznámky" "Obnovte šifrovanie vášho účtu pomocou iného zariadenia" + "Údaje o vašom účte, kontakty, predvoľby a zoznam konverzácií budú zachované" + "Stratíte svoju existujúcu históriu správ" + "Budete musieť znova overiť všetky existujúce zariadenia a kontakty" + "Obnovte svoju totožnosť iba vtedy, ak nemáte prístup k inému prihlásenému zariadeniu a stratili ste kľúč na obnovenie." + "Ak nie ste prihlásení do žiadneho iného zariadenia a stratili ste kľúč na obnovenie, budete musieť znovu obnoviť svoju identitu, aby ste mohli pokračovať v používaní aplikácie. " + "Znovu nastavte svoju totožnosť v prípade, že ju nemôžete potvrdiť iným spôsobom" "Vypnúť" "Stratíte prístup k svojim zašifrovaným správam, ak sa odhlásite zo všetkých zariadení" "Ste si istí, že chcete vypnúť zálohovanie?" @@ -51,4 +57,11 @@ "Uistite sa, že kľúč na obnovenie môžete uložiť niekde v bezpečí" "Úspešné nastavenie obnovy" "Nastaviť obnovenie" + "Áno, znovu nastaviť teraz" + "Tento proces je nezvratný." + "Naozaj chcete obnoviť svoje šifrovanie?" + "Nastala neznáma chyba. Skontrolujte, či je heslo vášho účtu správne a skúste to znova." + "Zadajte…" + "Potvrďte, že chcete obnoviť svoje šifrovanie." + "Ak chcete pokračovať, zadajte heslo účtu" diff --git a/features/securebackup/impl/src/main/res/values-sv/translations.xml b/features/securebackup/impl/src/main/res/values-sv/translations.xml index 5216a7ed96..58a8c8571b 100644 --- a/features/securebackup/impl/src/main/res/values-sv/translations.xml +++ b/features/securebackup/impl/src/main/res/values-sv/translations.xml @@ -16,6 +16,12 @@ "Följ anvisningarna för att skapa en ny återställningsnyckel" "Spara din nya återställningsnyckel i en lösenordshanterare eller krypterad anteckning" "Återställ krypteringen för ditt konto med en annan enhet" + "Dina kontouppgifter, kontakter, inställningar och chattlistor kommer bevaras" + "Du kommer att förlora din befintliga meddelandehistorik" + "Du måste verifiera alla dina befintliga enheter och kontakter igen" + "Återställ bara din identitet om du inte har tillgång till en annan inloggad enhet och du har tappat bort din återställningsnyckel." + "Om du inte är inloggad på någon annan enhet och du har tappat bort din återställningsnyckel måste du återställa din identitet för att fortsätta använda appen. " + "Återställ din identitet ifall du inte kan bekräfta på annat sätt" "Stäng av" "Du kommer att förlora dina krypterade meddelanden om du loggas ut från alla enheter." "Är du säker på att du vill stänga av säkerhetskopiering?" @@ -51,4 +57,11 @@ "Se till att du kan lagra din återställningsnyckel någonstans säkert" "Konfiguration av återställning lyckades" "Ställ in återställning" + "Ja, återställ nu" + "Denna process är irreversibel." + "Är du säker på att du vill återställa din kryptering?" + "Ett okänt fel inträffade. Kontrollera att ditt kontolösenord är korrekt och försök igen." + "Ange …" + "Bekräfta att du vill återställa din kryptering." + "Ange ditt kontolösenord för att fortsätta" diff --git a/features/securebackup/impl/src/main/res/values-uk/translations.xml b/features/securebackup/impl/src/main/res/values-uk/translations.xml index 1d1b9d2526..98288f1aa6 100644 --- a/features/securebackup/impl/src/main/res/values-uk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-uk/translations.xml @@ -16,6 +16,12 @@ "Дотримуйтесь інструкцій, щоб створити новий ключ відновлення" "Збережіть новий ключ відновлення у менеджері паролів або зашифрованій нотатці" "Скинути шифрування облікового запису за допомогою іншого пристрою" + "Дані вашого облікового запису, контакти, налаштування й чати будуть збережені" + "Ви втратите свою наявну історію повідомлень" + "Вам доведеться підтвердити всі наявні пристрої та контакти знову" + "Скидайте ідентичність тільки якщо ви не маєте доступу до інших пристроїв в обліковому записі та втратили свій ключ відновлення." + "Якщо ви не увійшли на інших пристроях та втратили свій ключ відновлення, то вам доведеться скинути свою ідентичність, щоб продовжити використовувати застосунок. " + "Скиньте свою ідентичність, якщо не можете підтвердити іншим способом" "Вимкнути" "Ви втратите зашифровані повідомлення, якщо вийдете з усіх пристроїв." "Ви впевнені, що хочете вимкнути резервне копіювання?" @@ -51,4 +57,10 @@ "Переконайтеся, що ви можете зберігати ключ відновлення в безпечному місці" "Налаштування відновлення виконано успішно" "Налаштувати відновлення" + "Так, скинути зараз" + "Цей процес незворотний." + "Ви впевнені, що хочете скинути шифрування?" + "Ввести…" + "Підтвердьте, що ви хочете скинути шифрування." + "Введіть пароль облікового запису, щоб продовжити" diff --git a/features/securebackup/impl/src/main/res/values-zh/translations.xml b/features/securebackup/impl/src/main/res/values-zh/translations.xml index a984d72208..f350d6ff62 100644 --- a/features/securebackup/impl/src/main/res/values-zh/translations.xml +++ b/features/securebackup/impl/src/main/res/values-zh/translations.xml @@ -16,12 +16,18 @@ "按照说明创建新的恢复密钥" "将新的恢复密钥保存在密码管理器或加密备忘录中" "使用其他设备重置账户的加密" + "您的账户信息、联系人、偏好设置和聊天列表将被保留" + "您将丢失现有的消息历史记录" + "您将需要再次验证所有您的现有设备和联系人" + "仅当您无法访问其他已登录设备并且丢失了恢复密钥时才重置您的身份。" + "如果您未登录任何其他设备,并且丢失了恢复密钥,则需要重置身份才能继续使用该应用。" + "如果您无法通过其他方式确认,请重置您的身份" "关闭" "如果您登出所有设备,您的加密消息将丢失。" "您确定要关闭备份吗?" "关闭备份将删除您当前的加密密钥备份并关闭其他安全功能。在这种情况下,你将:" "新设备上没有加密消息的历史记录" - "如果您在所有设备上登出了 %1$s,那将无法访问加密的消息" + "如果您在所有设备上登出了 %1$s,那将无法访问加密消息" "您确定要关闭备份吗?" "如果您丢失了现有的恢复密钥,请获取新的恢复密钥。更改恢复密钥后,您的旧密钥将不再起作用。" "生成新的恢复密钥" @@ -51,4 +57,10 @@ "确保将恢复密钥存储在安全的地方" "恢复设置成功" "设置恢复" + "是的,立即重置" + "此过程不可逆。" + "您确定要重置加密吗?" + "输入…" + "确认您要重置加密。" + "输入您的账户密码以继续" diff --git a/features/signedout/impl/src/main/res/values-nl/translations.xml b/features/signedout/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..90ee4efd53 --- /dev/null +++ b/features/signedout/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,8 @@ + + + "Je hebt je wachtwoord gewijzigd in een andere sessie" + "Je hebt deze sessie verwijderd in een andere sessie" + "De beheerder van je server heeft je toegang ongeldig gemaakt" + "Je bent mogelijk uitgelogd om een van de onderstaande redenen. Meld je opnieuw aan om %s te blijven gebruiken." + "Je bent uitgelogd" + diff --git a/features/userprofile/shared/src/main/res/values-nl/translations.xml b/features/userprofile/shared/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..ec08bf8650 --- /dev/null +++ b/features/userprofile/shared/src/main/res/values-nl/translations.xml @@ -0,0 +1,10 @@ + + + "Blokkeren" + "Geblokkeerde gebruikers kunnen je geen berichten sturen en al hun berichten worden verborgen. Je kunt ze op elk moment deblokkeren." + "Gebruiker blokkeren" + "Deblokkeren" + "Je zult alle berichten van hen weer kunnen zien." + "Gebruiker deblokkeren" + "Er is een fout opgetreden bij het starten van een chat" + diff --git a/features/userprofile/shared/src/main/res/values-zh/translations.xml b/features/userprofile/shared/src/main/res/values-zh/translations.xml index d70689b326..83f884cecb 100644 --- a/features/userprofile/shared/src/main/res/values-zh/translations.xml +++ b/features/userprofile/shared/src/main/res/values-zh/translations.xml @@ -4,7 +4,7 @@ "被封禁的用户无法给你发消息,并且他们的消息会被隐藏。你可以随时解封。" "封禁用户" "解封" - "你可以重新接收他们的消息。" + "可以重新接收他们的消息。" "解封用户" "在开始聊天时发生了错误" diff --git a/features/verifysession/impl/src/main/res/values-cs/translations.xml b/features/verifysession/impl/src/main/res/values-cs/translations.xml index 96d9aa0aa9..7d012a09da 100644 --- a/features/verifysession/impl/src/main/res/values-cs/translations.xml +++ b/features/verifysession/impl/src/main/res/values-cs/translations.xml @@ -1,9 +1,11 @@ + "Nemůžete potvrdit?" "Vytvoření nového klíče pro obnovení" "Ověřte toto zařízení a nastavte zabezpečené zasílání zpráv." "Potvrďte, že jste to vy" "Použít jiné zařízení" + "Použít klíč pro obnovení" "Nyní můžete bezpečně číst nebo odesílat zprávy, a kdokoli, s kým chatujete, může tomuto zařízení důvěřovat." "Zařízení ověřeno" "Použít jiné zařízení" diff --git a/features/verifysession/impl/src/main/res/values-fr/translations.xml b/features/verifysession/impl/src/main/res/values-fr/translations.xml index 6750f48956..b1f3ad365b 100644 --- a/features/verifysession/impl/src/main/res/values-fr/translations.xml +++ b/features/verifysession/impl/src/main/res/values-fr/translations.xml @@ -1,9 +1,11 @@ + "Confirmation impossible ?" "Créer une nouvelle clé de récupération" "Vérifier cette session pour configurer votre messagerie sécurisée." "Confirmez votre identité" "Utiliser une autre session" + "Utiliser la clé de récupération" "Vous pouvez désormais lire ou envoyer des messages en toute sécurité, et toute personne avec qui vous discutez peut également faire confiance à cette session." "Session vérifiée" "Utiliser une autre session" diff --git a/features/verifysession/impl/src/main/res/values-it/translations.xml b/features/verifysession/impl/src/main/res/values-it/translations.xml index ac7036eebb..d36733d08b 100644 --- a/features/verifysession/impl/src/main/res/values-it/translations.xml +++ b/features/verifysession/impl/src/main/res/values-it/translations.xml @@ -1,9 +1,11 @@ + "Non puoi confermare?" "Crea una nuova chiave di recupero" "Verifica questo dispositivo per segnare i tuoi messaggi come sicuri." "Conferma la tua identità" "Usa un altro dispositivo" + "Usa la chiave di recupero" "Ora puoi leggere o inviare messaggi in tutta sicurezza e anche chi chatta con te può fidarsi di questo dispositivo." "Dispositivo verificato" "Usa un altro dispositivo" diff --git a/features/verifysession/impl/src/main/res/values-nl/translations.xml b/features/verifysession/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..39744242c5 --- /dev/null +++ b/features/verifysession/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,17 @@ + + + "Er lijkt iets niet goed te gaan. Of er is een time-out opgetreden of het verzoek is geweigerd." + "Bevestig dat de emoji\'s hieronder overeenkomen met de emoji\'s in je andere sessie." + "Vergelijk emoji\'s" + "Je nieuwe sessie is nu geverifieerd. Het heeft toegang tot je versleutelde berichten en andere gebruikers zullen het als vertrouwd beschouwen." + "Bewijs dat jij het bent om toegang te krijgen tot je versleutelde berichtgeschiedenis." + "Open een bestaande sessie" + "Verificatie opnieuw proberen" + "Ik ben er klaar voor" + "Wachten om te vergelijken" + "Vergelijk de unieke emoji\'s, ze dienen in dezelfde volgorde te worden weergegeven." + "Ze komen niet overeen" + "Ze komen overeen" + "Accepteer het verzoek tot verificatie in je andere sessie om door te gaan." + "Wachten om verzoek te accepteren" + diff --git a/features/verifysession/impl/src/main/res/values-pl/translations.xml b/features/verifysession/impl/src/main/res/values-pl/translations.xml index 07a3304ed9..506889fbae 100644 --- a/features/verifysession/impl/src/main/res/values-pl/translations.xml +++ b/features/verifysession/impl/src/main/res/values-pl/translations.xml @@ -1,9 +1,11 @@ + "Nie możesz potwierdzić?" "Utwórz nowy klucz przywracania" "Zweryfikuj to urządzenie, aby skonfigurować bezpieczne przesyłanie wiadomości." "Potwierdź, że to Ty" "Użyj innego urządzenia" + "Użyj klucza przywracania" "Teraz możesz bezpiecznie czytać i wysyłać wiadomości, każdy z kim czatujesz również może ufać temu urządzeniu." "Urządzenie zweryfikowane" "Użyj innego urządzenia" diff --git a/features/verifysession/impl/src/main/res/values-zh/translations.xml b/features/verifysession/impl/src/main/res/values-zh/translations.xml index b13b0e7686..765da43569 100644 --- a/features/verifysession/impl/src/main/res/values-zh/translations.xml +++ b/features/verifysession/impl/src/main/res/values-zh/translations.xml @@ -1,9 +1,11 @@ + "无法确认?" "创建新的恢复密钥" "验证此设备以开始安全地收发消息。" "确认这是你" "使用其他设备" + "使用恢复密钥" "现在,您可以安全地阅读或发送消息,与您聊天的人也会信任此设备。" "设备已验证" "使用其他设备" @@ -13,7 +15,7 @@ "比较表情符号" "确认以下数字与其他会话中显示的一致。" "比较数字" - "你的新设备已经成功验证。现在新设备可以访问加密信息,别的用户也会信任这个设备。" + "新设备已经成功验证。现在新设备可以访问加密信息,其他用户也会信任这个设备。" "输入恢复密钥" "证明自己的身份以访问加密历史消息。" "打开已有会话" diff --git a/libraries/androidutils/src/main/res/values-nl/translations.xml b/libraries/androidutils/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..318e57815d --- /dev/null +++ b/libraries/androidutils/src/main/res/values-nl/translations.xml @@ -0,0 +1,4 @@ + + + "Er is geen compatibele app gevonden om deze actie uit te voeren." + diff --git a/libraries/eventformatter/impl/src/main/res/values-cs/translations.xml b/libraries/eventformatter/impl/src/main/res/values-cs/translations.xml index e99778b71c..ab203f1d3b 100644 --- a/libraries/eventformatter/impl/src/main/res/values-cs/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-cs/translations.xml @@ -45,6 +45,12 @@ "Odstranili jste název místnosti" "%1$s neprovedl(a) žádné změny" "Neprovedli jste žádné změny" + "%1$s změnil(a) připnuté zprávy" + "Změnili jste připnuté zprávy" + "%1$s připnul(a) zprávu" + "Připnuli jste zprávu" + "%1$s odepnul(a) zprávu" + "Odepnuli jste zprávu" "%1$s pozvánku odmítl(a)" "Odmítli jste pozvání" "%1$s odebral(a) %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml b/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml index 664aeebeaf..7cc18968de 100644 --- a/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml @@ -45,6 +45,12 @@ "Vous avez supprimé le nom du salon" "%1$s n‘a fait aucun changement visible" "Vous n‘avez fait aucun changement visible" + "%1$s a modifié les messages épinglés" + "Vous avez modifié les messages épinglés" + "%1$s a épinglé un message" + "Vous avez épinglé un message" + "%1$s a désépinglé un message" + "Vous avez désépinglé un message" "%1$s a rejeté l’invitation" "Vous avez refusé l’invitation" "%1$s a supprimé %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-it/translations.xml b/libraries/eventformatter/impl/src/main/res/values-it/translations.xml index 2d391404c7..02e1cebef0 100644 --- a/libraries/eventformatter/impl/src/main/res/values-it/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-it/translations.xml @@ -45,6 +45,12 @@ "Hai rimosso il nome della stanza" "%1$s non ha apportato modifiche" "Non hai apportato modifiche" + "%1$s ha modificato i messaggi fissati" + "Hai modificato i messaggi fissati" + "%1$s ha fissato un messaggio" + "Hai fissato un messaggio" + "%1$s ha rimosso un messaggio dai fissati" + "Hai rimosso un messaggio dai fissati" "%1$s ha rifiutato l\'invito" "Hai rifiutato l\'invito" "%1$s ha rimosso %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml b/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..a29c433f66 --- /dev/null +++ b/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,56 @@ + + + "(afbeelding is ook gewijzigd)" + "Je hebt je afbeelding gewijzigd" + "%1$s heeft de weergavenaam aangepast van %2$s naar %3$s" + "Je hebt je weergavenaam aangepast van %1$s naar %2$s" + "%1$s heeft de weergavenaam verwijderd (dit was %2$s)" + "Je hebt je weergavenaam verwijderd (dit was %1$s)" + "%1$s heeft de weergavenaam %2$s aangenomen" + "Je hebt de weergavenaam %1$s aangenomen" + "%1$s heeft de kamerafbeelding gewijzigd" + "Je hebt de kamerafbeelding gewijzigd" + "%1$s heeft de kamerafbeelding verwijderd" + "Je hebt de kamerafbeelding verwijderd" + "%1$s heeft %2$s verbannen" + "Je hebt %1$s verbannen" + "%1$s heeft de kamer gemaakt" + "Je hebt de kamer gemaakt" + "%1$s heeft %2$s uitgenodigd" + "%1$s heeft de uitnodiging geaccepteerd" + "Je hebt de uitnodiging geaccepteerd" + "Jij hebt %1$s uitgenodigd" + "%1$s heeft je uitgenodigd" + "%1$s is tot de kamer toegetreden" + "Je bent toegetreden tot de kamer" + "%1$s heeft gevraagd om toe te treden" + "%1$s heeft %2$s toegestaan toe te treden" + "Je hebt %1$s toegestaan toe te treden" + "Je hebt gevraagd om toe te treden" + "%1$s heeft %2$s\'s verzoek om toe te treden afgewezen" + "Je hebt %1$s\'s verzoek om toe te treden afgewezen" + "%1$s heeft je verzoek om toe te treden afgewezen" + "%1$s wil niet meer toetreden" + "Je hebt je verzoek om toe te treden geannuleerd" + "%1$s verliet de kamer" + "Je hebt de kamer verlaten" + "%1$s heeft de kamernaam gewijzigd naar: %2$s" + "Je hebt de kamernaam gewijzigd naar: %1$s" + "%1$s heeft de kamernaam verwijderd" + "Je hebt de kamernaam verwijderd" + "%1$s heeft de uitnodiging afgewezen" + "Je hebt de uitnodiging afgewezen" + "%1$s heeft %2$s verwijderd" + "Je hebt %1$s verwijderd" + "%1$s heeft %2$s in deze kamer uitgenodigd" + "Je hebt %1$s in deze kamer uitgenodigd" + "%1$s heeft de uitnodiging aan %2$s om toe te treden tot de kamer ingetrokken" + "Je hebt de uitnodiging aan %1$s om toe te treden tot de kamer ingetrokken" + "%1$s heeft het onderwerp gewijzigd naar: %2$s" + "Je hebt het onderwerp gewijzigd naar: %1$s" + "%1$s heeft het kameronderwerp verwijderd" + "Je hebt het kamerondewerp verwijderd" + "%1$s heeft %2$s ontbannen" + "Jij hebt %1$s ontbannen" + "%1$s heeft een onbekende lidmaatschapswijziging" + diff --git a/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml b/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml index 2efaca2b08..60f442bb75 100644 --- a/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml @@ -45,6 +45,12 @@ "Usunąłeś nazwę pokoju" "%1$s nie wprowadził żadnych zmian" "Nie wprowadzono żadnych zmian" + "%1$s zmienił przypięte wiadomości" + "Zmieniłeś przypięte wiadomości" + "%1$s przypiął wiadomość" + "Przypiąłeś wiadomość" + "%1$s odpiął wiadomość" + "Odpiąłeś wiadomość" "%1$s odrzucił zaproszenie" "Odrzuciłeś zaproszenie" "%1$s usunął %2$s" diff --git a/libraries/eventformatter/impl/src/main/res/values-uz/translations.xml b/libraries/eventformatter/impl/src/main/res/values-uz/translations.xml index 5afcc9b061..91ac192205 100644 --- a/libraries/eventformatter/impl/src/main/res/values-uz/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-uz/translations.xml @@ -31,7 +31,7 @@ "%1$s %2$sning qo\'shilish haqidagi iltimosini rad etdi" "Siz %1$sning qo\'shiliz iltimosini rad etdingiz" "%1$s sizni qo\'shilish iltimosingizni rad etdi" - "%1$ endi qo\'shilishdan manfaatdor emas" + "%1$s endi qo\'shilishdan manfaatdor emas" "Siz qoʻshilish soʻrovingizni bekor qildingiz" "%1$sxonani tark etdi" "Siz xonani tark etdingiz" @@ -41,12 +41,12 @@ "Siz xonani nomini o\'chirib tashladingiz" "%1$staklifni rad etdi" "Siz taklifni rad etdingiz" - "%1$o\'chirildi%2$s" - "siz o\'chirildingiz%1$s" + "%1$s o\'chirildi %2$s" + "Siz o\'chirildingiz %1$s" "%1$s taklifnoma yubordi %2$sga xonaga qo\'shilish uchun" - "Siz taklifnoma yubordingiz %1$sga xonaga qo\'shilishi uchun" - "%1$s taklifni %2$sga xonaga qo\'shilish uchun bekor qildi" - "Siz xonaga qo\'shilish taklifini $1$s ga bekor qildingiz" + "Siz taklifnoma yubordingiz %1$s ga xonaga qo\'shilishi uchun" + "%1$s taklifni %2$s ga xonaga qo\'shilish uchun bekor qildi" + "Siz xonaga qo\'shilish taklifini %1$s ga bekor qildingiz" "%1$s mavzuni %2$s o\'zgartirdi" "Siz mavzuni %1$s ga o\'zgartirdingiz" "%1$s xonani mavzusini o\'chirib tashladi" diff --git a/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml b/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml index 76a61c6ccc..c968d6c75c 100644 --- a/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml @@ -45,6 +45,12 @@ "你移除了房间名称" "%1$s 没有任何更改" "您未进行任何更改" + "%1$s 更改了置顶消息" + "您更改了置顶消息" + "%1$s 置顶了一条消息" + "您置顶了一条消息" + "%1$s 取消置顶了一条消息" + "您取消置顶了一条消息" "%1$s 拒绝了邀请" "你拒绝了邀请" "%1$s 移除了 %2$s" diff --git a/libraries/matrixui/src/main/res/values-nl/translations.xml b/libraries/matrixui/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..1886b6424c --- /dev/null +++ b/libraries/matrixui/src/main/res/values-nl/translations.xml @@ -0,0 +1,4 @@ + + + "%1$s (%2$s) heeft je uitgenodigd" + diff --git a/libraries/permissions/api/src/main/res/values-nl/translations.xml b/libraries/permissions/api/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..8f4eac6d8a --- /dev/null +++ b/libraries/permissions/api/src/main/res/values-nl/translations.xml @@ -0,0 +1,7 @@ + + + "Geef toestemming in de systeeminstellingen om de applicatie de camera te laten gebruiken." + "Geef hiervoor toestemming in de systeeminstellingen." + "Geef toestemming in de systeeminstellingen om de applicatie de microfoon te laten gebruiken." + "Geef toestemming in de systeeminstellingen om de applicatie meldingen te laten weergeven." + diff --git a/libraries/push/impl/src/main/res/values-de/translations.xml b/libraries/push/impl/src/main/res/values-de/translations.xml index 0d1988ecba..35924e6247 100644 --- a/libraries/push/impl/src/main/res/values-de/translations.xml +++ b/libraries/push/impl/src/main/res/values-de/translations.xml @@ -3,6 +3,7 @@ "Anruf" "Auf Ereignisse achten" "Laute Benachrichtigungen" + "Klingelnde Anrufe" "Stumme Benachrichtigungen" "%1$s: %2$d Nachricht" @@ -13,6 +14,7 @@ "%d Mitteilungen" "Mitteilung" + "Eingehender Anruf" "** Fehler beim Senden - bitte Raum öffnen" "Beitreten" "Ablehnen" diff --git a/libraries/push/impl/src/main/res/values-nl/translations.xml b/libraries/push/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..7bb304d898 --- /dev/null +++ b/libraries/push/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,50 @@ + + + "Bellen" + "Wachten op gebeurtenissen" + "Luide meldingen" + "Stille meldingen" + + "%1$s: %2$d bericht" + "%1$s: %2$d berichten" + + + "%d melding" + "%d meldingen" + + "Melding" + "** Verzenden is mislukt - open de kamer" + "Deelnemen" + "Afwijzen" + + "%d uitnodiging" + "%d uitnodigingen" + + "Nodigde je uit om te chatten" + "Nieuwe berichten" + + "%d nieuw bericht" + "%d nieuwe berichten" + + "Reageerde met %1$s" + "Snel antwoord" + "Nodigde je uit om tot de kamer toe te treden" + "Mij" + "Je bekijkt de melding! Klik hier!" + "%1$s: %2$s" + "%1$s: %2$s %3$s" + + "%d ongelezen bericht met melding" + "%d ongelezen berichten met melding" + + "%1$s en %2$s" + "%1$s in %2$s" + "%1$s in %2$s en %3$s" + + "%d kamer" + "%d kamers" + + "Achtergrondsynchronisatie" + "Google-services" + "Geen geldige Google Play-services gevonden. Meldingen werken mogelijk niet goed." + diff --git a/libraries/push/impl/src/main/res/values-zh/translations.xml b/libraries/push/impl/src/main/res/values-zh/translations.xml index 9a4e2f47d2..88ac5dfa89 100644 --- a/libraries/push/impl/src/main/res/values-zh/translations.xml +++ b/libraries/push/impl/src/main/res/values-zh/translations.xml @@ -3,6 +3,7 @@ "通话" "监听事件" "嘈杂通知" + "来电振铃" "静默通知" "%1$s:%2$d 条消息" @@ -11,6 +12,7 @@ "%d 条通知" "通知" + "来电" "** 无法发送——请打开房间" "加入" "拒绝" diff --git a/libraries/textcomposer/impl/src/main/res/values-nl/translations.xml b/libraries/textcomposer/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..39158588d7 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,25 @@ + + + "Bijlage toevoegen" + "Lijst met opsommingstekens in-/uitschakelen" + "Opmaakopties sluiten" + "Codeblok in-/uitschakelen" + "Bericht…" + "Maak een link" + "Link bewerken" + "Vetgedrukte opmaak toepassen" + "Cursieve opmaak toepassen" + "Doorgestreepte opmaak toepassen" + "Onderstreepte opmaak toepassen" + "Modus volledig scherm in-/uitschakelen" + "Inspringen" + "Inline code-opmaak toepassen" + "Link instellen" + "Genummerde lijst in-/uitschakelen" + "Open opstelopties" + "Citaat in-/uitschakelen" + "Link verwijderen" + "Inspringing ongedaan maken" + "Link" + "Vasthouden om op te nemen" + diff --git a/libraries/troubleshoot/impl/src/main/res/values-zh/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-zh/translations.xml index 22354b62b7..74b759f622 100644 --- a/libraries/troubleshoot/impl/src/main/res/values-zh/translations.xml +++ b/libraries/troubleshoot/impl/src/main/res/values-zh/translations.xml @@ -7,5 +7,5 @@ "尝试修复" "所有测试均成功通过。" "排查通知问题" - "有些测试需要你注意。请查看详情。" + "有些测试需要注意。请查看详情。" 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 955c4eab3d..91c45ebe2e 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -272,12 +272,6 @@ "Гэй, пагавары са мной у %1$s: %2$s" "%1$s Android" "Паведаміць аб памылцы з дапамогай Rageshake" - "Дадзеныя вашага ўліковага запісу, кантакты, налады і спіс чатаў будуць захаваны" - "Вы страціце існуючую гісторыю паведамленняў" - "Вам трэба будзе зноў запэўніць ўсе вашы існуючыя прылады і кантакты" - "Працягвайце, толькі калі вы ўпэўненыя, што страцілі ўсе астатнія прылады і ключ аднаўлення." - "Калі вы не ўвайшлі ў сістэму на іншых прыладах і страцілі ключ аднаўлення, вам неабходна скінуць ключы пацверджання, каб працягнуць выкарыстанне прыкладання." - "Скіньце ключы пацверджання, калі вы не можаце пацвердзіць яго іншым спосабам" "Не ўдалося выбраць носьбіт, паўтарыце спробу." "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз." "Не атрымалася загрузіць медыяфайлы, паспрабуйце яшчэ раз." @@ -289,12 +283,6 @@ "%1$d Замацаваных паведамленняў" "Замацаваныя паведамленні" - "Так, скінуць зараз" - "Гэты працэс незваротны." - "Вы ўпэўнены, што хочаце скінуць шыфраванне?" - "Увод…" - "Пацвердзіце, што вы хочаце скінуць шыфраванне" - "Каб працягнуць, увядзіце пароль уліковага запісу" "Замацаваныя паведамленні" "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз." "Не ўдалося атрымаць інфармацыю пра карыстальніка" 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 39e0610883..7c901b0422 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -93,6 +93,7 @@ "Nahlásit chybu" "Nahlásit obsah" "Obnovit" + "Obnovit identitu" "Zkusit znovu" "Opakovat dešifrování" "Uložit" @@ -263,6 +264,7 @@ Důvod: %1$s." "Některé zprávy nebyly odeslány" "Omlouváme se, došlo k chybě" "Autenticitu této zašifrované zprávy nelze na tomto zařízení zaručit." + "Není zašifrováno." "Šifrováno neznámým nebo smazaným zařízením." "Šifrováno zařízením, které nebylo ověřeno jeho vlastníkem." "Šifrováno neověřeným uživatelem." @@ -273,6 +275,15 @@ Důvod: %1$s." "Výběr média se nezdařil, zkuste to prosím znovu." "Nahrání média se nezdařilo, zkuste to prosím znovu." "Nahrání média se nezdařilo, zkuste to prosím znovu." + "Přidržte zprávu a vyberte „%1$s“, kterou chcete zahrnout sem." + "Připněte důležité zprávy, aby je bylo možné snadno najít" + + "%1$d Připnutá zpráva" + "%1$d Připnuté zprávy" + "%1$d Připnutých zpráv" + + "Připnuté zprávy" + "Připnuté zprávy" "Nahrání média se nezdařilo, zkuste to prosím znovu." "Nepodařilo se načíst údaje o uživateli" "Zablokovat" @@ -284,6 +295,7 @@ Důvod: %1$s." "Odblokovat uživatele" "%1$s z %2$s" "%1$s Připnuté zprávy" + "Načítání zprávy…" "Zobrazit vše" "Chat" "Sdílet polohu" 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 e101fb1c8c..56c541cc48 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -109,6 +109,7 @@ "Foto aufnehmen" "Für Optionen tippen" "Erneut versuchen" + "Entpinnen" "Quellcode anzeigen" "Ja" "Über" @@ -120,6 +121,7 @@ "Blockierte Nutzer" "Sprechblasen" "Aktiver Anruf (nicht unterstützt)" + "Aufruf gestartet" "Chat-Backup" "Copyright" "Raum wird erstellt…" @@ -128,12 +130,16 @@ "Dekodierungsfehler" "Entwickleroptionen" "Direktnachricht" + "Nicht mehr anzeigen" "(bearbeitet)" "Bearbeitung" "* %1$s %2$s" "Verschlüsselung aktiviert" "PIN eingeben" "Fehler" + "Es ist ein Fehler aufgetreten, du erhältst möglicherweise keine Benachrichtigungen für neue Nachrichten. Bitte behebe das Problem mit den Benachrichtigungen in den Einstellungen. + +Grund: %1$s." "Alle" "Fehlgeschlagen" "Favorit" @@ -163,6 +169,7 @@ "Keine Ergebnisse" "Kein Raumname" "Offline" + "Open-Source-Lizenzen" "oder" "Passwort" "Personen" @@ -197,6 +204,7 @@ "Suchergebnisse" "Sicherheit" "Gesehen von" + "Senden an" "Wird gesendet…" "Senden fehlgeschlagen" "Gesendet" @@ -249,6 +257,10 @@ "%1$s hat nicht die Erlaubnis auf dein Mikrofon zuzugreifen. Aktiviere den Zugriff, um eine Sprachnachricht aufzunehmen." "Einige Nachrichten wurden nicht gesendet" "Entschuldigung, es ist ein Fehler aufgetreten" + "Die Authentizität dieser verschlüsselten Nachricht kann auf diesem Gerät nicht garantiert werden." + "Verschlüsselt von einem unbekannten oder gelöschten Gerät." + "Verschlüsselt durch ein Gerät, das nicht von seinem Besitzer verifiziert wurde." + "Verschlüsselt durch einen nicht verifizierten Benutzer." "🔐️ Begleite mich auf %1$s" "Hey, sprich mit mir auf %1$s: %2$s" "%1$s Android" @@ -265,6 +277,9 @@ "Blockierung aufheben" "Der Nutzer kann dir wieder Nachrichten senden & alle Nachrichten des Nutzers werden wieder angezeigt." "Blockierung aufheben" + "%1$svon %2$s" + "%1$s Angepinnte Nachrichten" + "Alle anzeigen" "Chat" "Standort teilen" "Meinen Standort teilen" 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 31e32b2a27..4dace2a902 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -80,7 +80,7 @@ "OK" "Seadistused" "Ava rakendusega" - "Kinnita" + "Tõsta esile" "Kiirvastus" "Tsiteeri" "Reageeri" @@ -111,7 +111,7 @@ "Tee pilt" "Valikuteks klõpsa" "Proovi uuesti" - "Eemalda kinnitus" + "Eemalda esiletõstmine" "Vaata lähtekoodi" "Jah" "Rakenduse teave" @@ -268,12 +268,6 @@ Põhjus: %1$s." "Hei, suhtle minuga %1$s võrgus: %2$s" "%1$s Android" "Veast teatamiseks raputa nutiseadet ägedalt" - "Sinu kasutajakonto andmed, kontaktid, eelistused ja vestluste loend säiluvad" - "Sa kaotad seniste sõnumite ajaloo" - "Sa pead kõik oma olemasolevad seadmed ja kontaktid uuesti verifitseerima" - "Lähtesta oma identiteet vaid siis, kui sul pole ligipääsu mitte ühelegi oma seadmele ja sa oled kaotanud oma taastevõtme." - "Kui sa soovid jätkata selle rakenduse kasutamist ja sa pole mitte üheski seadmes sisse logitud ning oled kaotanud oma taastevõtme, siis tõesti pead lähtestama oma identiteedi. " - "Kui sa ühtegi muud võimalust ei leia, siis lähtesta oma identiteet." "Meediafaili valimine ei õnnestunud. Palun proovi uuesti." "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Meediafaili üleslaadimine ei õnnestunud. Palun proovi uuesti." @@ -284,12 +278,6 @@ Põhjus: %1$s." "%1$d esiletõstetud sõnumit" "Esiletõstetud sõnumid" - "Jah, lähtesta nüüd" - "See tegevus on tagasipöördumatu." - "Kas sa oled kindel, et soovid oma andmete krüptimist lähtestada?" - "Sisesta…" - "Palun kinnita, et soovid oma andmete krüptimist lähtestada." - "Jätkamaks sisesta oma kasutajakonto salasõna" "Esiletõstetud sõnumid" "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Kasutaja andmete laadimine ei õnnestunud" 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 a62f307a6f..8d39970ad7 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -80,6 +80,7 @@ "OK" "Ouvrir les paramètres" "Ouvrir avec" + "Épingler" "Réponse rapide" "Citer" "Réagissez" @@ -109,6 +110,7 @@ "Prendre une photo" "Appuyez pour afficher les options" "Essayer à nouveau" + "Désépingler" "Afficher la source" "Oui" "À propos" @@ -168,6 +170,7 @@ Raison: %1$s." "Aucun résultat" "Salon sans nom" "Hors ligne" + "Licences open source" "ou" "Mot de passe" "Personnes" @@ -255,6 +258,11 @@ Raison: %1$s." "%1$s n’a pas l’autorisation d’utiliser le microphone. Autorisez l’utilisation pour enregistrer un message vocal." "Certains messages n’ont pas été envoyés" "Désolé, une erreur s’est produite" + "L’authenticité de ce message chiffré ne peut être garantie sur cet appareil." + "Non chiffré." + "Chiffré par un appareil inconnu ou supprimé." + "Chiffré par un appareil non vérifié par son propriétaire." + "Chiffré par un utilisateur non vérifié." "🔐️ Rejoignez-moi sur %1$s" "Salut, parle-moi sur %1$s : %2$s" "%1$s Android" @@ -262,6 +270,14 @@ Raison: %1$s." "Échec de la sélection du média, veuillez réessayer." "Échec du traitement des médias à télécharger, veuillez réessayer." "Échec du téléchargement du média, veuillez réessayer." + "Cliquez (clic long) sur un message et choisissez « %1$s » pour qu‘il apparaisse ici." + "Épinglez les messages importants pour leur donner plus de visibilité" + + "%1$d message épinglé" + "%1$d messages épinglés" + + "Messages épinglés" + "Messages épinglés" "Échec du traitement des médias à télécharger, veuillez réessayer." "Impossible de récupérer les détails de l’utilisateur" "Bloquer" @@ -271,6 +287,10 @@ Raison: %1$s." "Débloquer" "Vous pourrez à nouveau voir tous ses messages." "Débloquer l’utilisateur" + "%1$s sur %2$s" + "%1$s Messages épinglés" + "Chargement du message…" + "Voir tout" "Discussion" "Partage de position" "Partager ma position" 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 84e16ed265..17468d55dc 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -268,21 +268,9 @@ Ok: %1$s." "Beszélgessünk itt: %1$s, %2$s" "%1$s Android" "Az eszköz rázása a hibajelentéshez" - "A fiókadatok, a kapcsolatok, a beállítások és a csevegéslista megmarad" - "Elveszíti meglévő üzenetelőzményeit" - "Újból ellenőriznie kell az összes meglévő eszközét és csevegőpartnerét" - "Csak akkor állítsa vissza a személyazonosságát, ha nem fér hozzá másik bejelentkezett eszközhöz, és elvesztette a helyreállítási kulcsot." - "Ha nincs bejelentkezve más eszközre, és elvesztette a helyreállítási kulcsot, akkor az alkalmazás használatának folytatásához vissza kell állítania személyazonosságát. " - "Állítsa vissza a személyazonosságát, ha más módon nem tudja megerősíteni" "Nem sikerült kiválasztani a médiát, próbálja újra." "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra." "Nem sikerült a média feltöltése, próbálja újra." - "Igen, visszaállítás most" - "Ez a folyamat visszafordíthatatlan." - "Biztos, hogy visszaállítja a titkosítást?" - "Adja meg…" - "Erősítse meg, hogy vissza szeretné állítani a titkosítást." - "A folytatáshoz adja meg fiókja jelszavát" "Kitűzött üzenetek" "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra." "Nem sikerült letölteni a felhasználói adatokat" 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 b727d3bac4..c190d39e42 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -80,6 +80,7 @@ "OK" "Impostazioni" "Apri con" + "Pin" "Risposta rapida" "Citazione" "Reagisci" @@ -90,6 +91,7 @@ "Segnala un problema" "Segnala contenuto" "Reimposta" + "Reimposta identità" "Riprova" "Riprova la decrittazione" "Salva" @@ -109,6 +111,7 @@ "Scatta foto" "Tocca per le opzioni" "Riprova" + "Rimuovi dai fissati" "Vedi codice sorgente" "Sì" "Informazioni" @@ -168,6 +171,7 @@ Motivo:. %1$s" "Nessun risultato" "Nessun nome della stanza" "Non in linea" + "Licenze open source" "o" "Password" "Persone" @@ -255,6 +259,11 @@ Motivo:. %1$s" "%1$s non ha l\'autorizzazione di accedere al microfono. Attiva l\'accesso per registrare un messaggio vocale." "Alcuni messaggi non sono stati inviati" "Siamo spiacenti, si è verificato un errore" + "L\'autenticità di questo messaggio cifrato non può essere garantita su questo dispositivo." + "Non cifrato." + "Cifrato da un dispositivo sconosciuto o eliminato." + "Cifrato da un dispositivo non verificato dal proprietario." + "Cifrato da un utente non verificato." "🔐️ Unisciti a me su %1$s" "Ehi, parliamo su %1$s: %2$s" "%1$s Android" @@ -262,6 +271,14 @@ Motivo:. %1$s" "Selezione del file multimediale fallita, riprova." "Elaborazione del file multimediale da caricare fallita, riprova." "Caricamento del file multimediale fallito, riprova." + "Premi su un messaggio e scegli “%1$s” per includerlo qui." + "Fissa i messaggi importanti così che possano essere trovati facilmente" + + "%1$d Messaggio fissato" + "%1$d Messaggi fissati" + + "Messaggi fissati" + "Messaggi fissati" "Elaborazione del file multimediale da caricare fallita, riprova." "Impossibile recuperare i dettagli dell\'utente" "Blocca" @@ -271,6 +288,10 @@ Motivo:. %1$s" "Sblocca" "Potrai vedere di nuovo tutti i suoi messaggi." "Sblocca utente" + "%1$s di %2$s" + "%1$s Messaggi fissati" + "Caricamento messaggio…" + "Mostra tutti" "Conversazione" "Condividi posizione" "Condividi la mia posizione" diff --git a/libraries/ui-strings/src/main/res/values-nl/translations.xml b/libraries/ui-strings/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..d4e650c1f5 --- /dev/null +++ b/libraries/ui-strings/src/main/res/values-nl/translations.xml @@ -0,0 +1,218 @@ + + + "Verwijderen" + "Wachtwoord verbergen" + "Spring naar einde" + "Alleen vermeldingen" + "Gedempt" + "Pagina %1$d" + "Pauzeren" + "PIN-veld" + "Afspelen" + "Peiling" + "Beeïndigde peiling" + "Reageer met %1$s" + "Reageer met andere emoji\'s" + "Gelezen door %1$s en %2$s" + "Gelezen door %1$s" + "Tik om alles weer te geven" + "Verwijder reactie met %1$s" + "Bestanden verzenden" + "Wachtwoord weergeven" + "Begin een oproep" + "Gebruikersmenu" + "Spraakbericht opnemen." + "Accepteren" + "Toevoegen aan tijdlijn" + "Terug" + "Annuleren" + "Kies foto" + "Wissen" + "Sluiten" + "Verificatie voltooien" + "Bevestigen" + "Voortzetten" + "Kopiëren" + "Kopieer link" + "Kopieer link naar bericht" + "Aanmaken" + "Creëer een kamer" + "Weigeren" + "Uitschakelen" + "Gereed" + "Bewerken" + "Peiling wijzigen" + "Activeren" + "Peiling beëindigen" + "Wachtwoord vergeten?" + "Doorsturen" + "Uitnodigen" + "Mensen uitnodigen" + "Nodig mensen uit voor %1$s" + "Nodig mensen uit voor %1$s" + "Uitnodigingen" + "Deelnemen" + "Meer informatie" + "Verlaten" + "Ruimte verlaten" + "Account beheren" + "Apparaten beheren" + "Volgende" + "Nee" + "Niet nu" + "OK" + "Instellingen" + "Openen met" + "Snel antwoord" + "Citeren" + "Reageren" + "Verwijderen" + "Antwoorden" + "Antwoord in subchat" + "Probleem melden" + "Inhoud melden" + "Opnieuw proberen" + "Decryptie opnieuw proberen" + "Opslaan" + "Zoeken" + "Verzenden" + "Bericht verzenden" + "Delen" + "Link delen" + "Log opnieuw in" + "Uitloggen" + "Toch uitloggen" + "Overslaan" + "Starten" + "Chat starten" + "Verificatie starten" + "Tik om kaart te laden" + "Foto maken" + "Bron weergeven" + "Ja" + "Over" + "Beleid inzake redelijk gebruik" + "Geavanceerde instellingen" + "Geluid" + "Bubbels" + "Chat back-up" + "Copyright" + "Kamer maken…" + "Heeft de kamer verlaten" + "Decryptie fout" + "Ontwikkelaarsopties" + "(bewerkt)" + "Bewerken" + "* %1$s %2$s" + "Encryptie ingeschakeld" + "Fout" + "Iedereen" + "Bestand" + "Bestand opgeslagen in Downloads" + "Bericht doorsturen" + "GIF" + "Afbeelding" + "Als antwoord op %1$s" + "APK installeren" + "Deze Matrix-ID kan niet worden gevonden, dus de uitnodiging is mogelijk niet ontvangen." + "De kamer verlaten" + "Link gekopieerd naar klembord" + "Laden…" + + "%1$d lid" + "%1$d leden" + + "Bericht" + "Berichtindeling" + "Bericht verwijderd" + "Modern" + "Dempen" + "Geen resultaten" + "Offline" + "Wachtwoord" + "Personen" + "Permalink" + "Toestemming" + "Weet je zeker dat je deze peiling wilt beëindigen?" + "Peiling: %1$s" + "Totaal aantal stemmen: %1$s" + "Resultaten worden getoond nadat de peiling is afgelopen" + + "%d stem" + "%d stemmen" + + "Privacybeleid" + "Reactie" + "Reacties" + "Recovery key" + "Verversen…" + "Een fout melden" + "Melding ingediend" + "Uitgebreide tekstverwerker" + "Naam van de kamer" + "bijv. de naam van je project" + "Zoekresultaten" + "Beveiliging" + "Verzenden…" + "Server niet ondersteund" + "Server-URL" + "Instellingen" + "Gedeelde locatie" + "Chat starten…" + "Sticker" + "Geslaagd" + "Suggesties" + "Synchroniseren" + "Tekst" + "Kennisgevingen van derden" + "Subchat" + "Onderwerp" + "Waar gaat deze kamer over?" + "Kan niet ontsleutelen" + "Uitnodigingen konden niet naar een of meerdere gebruikers worden verzonden." + "Kan uitnodiging(en) niet verzenden" + "Dempen opheffen" + "Niet-ondersteunde gebeurtenis" + "Gebruikersnaam" + "Verificatie geannuleerd" + "Verificatie voltooid" + "Video" + "Spraakbericht" + "Wachten…" + "Bevestiging" + "Fout" + "Geslaagd" + "Waarschuwing" + "Het aanmaken van de permanente link is mislukt" + "%1$s kon de kaart niet laden. Probeer het later opnieuw." + "Het laden van berichten is mislukt" + "%1$s had geen toegang tot je locatie. Probeer het later opnieuw." + "%1$s heeft geen toegang tot je locatie. Je kunt dit inschakelen bij Instellingen." + "%1$s heeft geen toegang tot je locatie. Schakel toegang hieronder in." + "Sommige berichten zijn niet verzonden" + "Sorry, er is een fout opgetreden" + "🔐️ Sluit je bij mij aan op %1$s" + "Hé, praat met me op %1$s: %2$s" + "%1$s Android" + "Schudden om een bug te melden" + "Het selecteren van media is mislukt. Probeer het opnieuw." + "Het verwerken van media voor uploaden is mislukt. Probeer het opnieuw." + "Het uploaden van media is mislukt. Probeer het opnieuw." + "Het verwerken van media voor uploaden is mislukt. Probeer het opnieuw." + "Kon gebruikersgegevens niet ophalen" + "Blokkeren" + "Geblokkeerde gebruikers kunnen je geen berichten sturen en al hun berichten worden verborgen. Je kunt ze op elk moment deblokkeren." + "Gebruiker blokkeren" + "Deblokkeren" + "Je zult alle berichten van hen weer kunnen zien." + "Gebruiker deblokkeren" + "Locatie delen" + "Deel mijn locatie" + "Openen in Apple Maps" + "Openen in Google Maps" + "Openen in OpenStreetMap" + "Deel deze locatie" + "Locatie" + "Versie: %1$s (%2$s)" + "en" + 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 17df3fe3d7..ec6cd30f89 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -60,7 +60,7 @@ "Zakończ ankietę" "Wprowadź PIN" "Nie pamiętasz hasła?" - "Dalej" + "Przekaż dalej" "Wróć" "Zaproś" "Zaproś znajomych" @@ -82,6 +82,7 @@ "Ok" "Ustawienia" "Otwórz za pomocą" + "Przypnij" "Szybka odpowiedź" "Cytuj" "Dodaj reakcję" @@ -92,6 +93,7 @@ "Zgłoś błąd" "Zgłoś treść" "Resetuj" + "Zresetuj tożsamość" "Spróbuj ponownie" "Ponów próbę odszyfrowania" "Zapisz" @@ -101,8 +103,8 @@ "Udostępnij" "Udostępnij link" "Zaloguj się ponownie" - "Wyloguj się" - "Wyloguj się mimo to" + "Wyloguj" + "Wyloguj mimo to" "Pomiń" "Rozpocznij" "Rozpocznij chat" @@ -111,6 +113,7 @@ "Zrób zdjęcie" "Stuknij, by wyświetlić opcje" "Spróbuj ponownie" + "Odepnij" "Wyświetl źródło" "Tak" "O programie" @@ -280,6 +283,9 @@ Powód: %1$s." "Odblokuj" "Będziesz mógł ponownie zobaczyć wszystkie wiadomości od tego użytkownika." "Odblokuj użytkownika" + "%1$s z %2$s" + "%1$s przypiętych wiadomości" + "Wyświetl wszystkie" "Czat" "Udostępnij lokalizację" "Udostępnij moją lokalizację" 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 630717a136..c573f2b9c4 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -267,21 +267,9 @@ Razão: %1$s." "Alô! Fala comigo na %1$s: %2$s" "%1$s Android" "Agita o dispositivo em fúria para comunicar um problema" - "Os detalhes da tua conta, contactos, preferências e lista de conversas serão mantidos." - "Perderás o acesso ao teu histórico de mensagens existente" - "Necessitarás de verificar todos os teus dispositivos e contactos novamente." - "Repõe a tua identidade apenas se não tiveres acesso a mais nenhum dispositivo com sessão iniciada e se tiveres perdido a tua chave de recuperação." - "Se não tiveres sessão iniciada em nenhum outro dispositivo e perdeste o acesso à tua chave de recuperação, precisarás de repor a tua identidade para continuares a usar a aplicação. " - "Repõe a tua identidade caso não consigas confirmar de outra forma" "Falha ao selecionar multimédia, por favor tente novamente." "Falha ao processar multimédia para carregamento, por favor tente novamente." "Falhar ao carregar multimédia, por favor tente novamente." - "Sim, repor agora" - "Este processo é irreversível." - "Tens a certeza que pretendes repor a tua cifra?" - "Inserir…" - "Confirma que pretendes realmente repor a tua cifra." - "Insere a tua palavra-passe para continuares" "Falha ao processar multimédia para carregamento, por favor tente novamente." "Não foi possível obter os detalhes de utilizador." "Bloquear" 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 d087e9c8d3..37866d0d09 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -274,12 +274,6 @@ "Привет, поговори со мной по %1$s: %2$s" "%1$s Android" "Встряхните устройство, чтобы сообщить об ошибке" - "Данные вашей учетной записи, контакты, настройки и список чатов будут сохранены" - "Вы потеряете существующую историю сообщений" - "Вам нужно будет заново подтвердить все существующие устройства и контакты." - "Сбрасывайте данные только в том случае, если у вас нет доступа к другому устройству, на котором выполнен вход, и вы потеряли ключ восстановления." - "Если вы не вошли в систему на других устройствах и потеряли ключ восстановления, вам необходимо сбросить учетные данные, чтобы продолжить использование приложения. " - "Сбросьте ключи подтверждения, если вы не можете подтвердить свою личность другим способом." "Не удалось выбрать носитель, попробуйте еще раз." "Не удалось обработать медиафайл для загрузки, попробуйте еще раз." "Не удалось загрузить медиафайлы, попробуйте еще раз." @@ -291,12 +285,6 @@ "%1$d Закрепленных сообщений" "Закрепленные сообщения" - "Да, сбросить сейчас" - "Этот процесс необратим." - "Вы действительно хотите сбросить шифрование?" - "Ввод…" - "Подтвердите, что вы хотите сбросить шифрование." - "Введите пароль своей учетной записи, чтобы продолжить" "Закрепленные сообщения" "Не удалось обработать медиафайл для загрузки, попробуйте еще раз." "Не удалось получить данные о пользователе" 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 497f2af1fb..c300012026 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -272,12 +272,6 @@ Dôvod: %1$s." "Ahoj, porozprávajte sa so mnou na %1$s: %2$s" "%1$s Android" "Zúrivo potriasť pre nahlásenie chyby" - "Údaje o vašom účte, kontakty, predvoľby a zoznam konverzácií budú zachované" - "Stratíte svoju existujúcu históriu správ" - "Budete musieť znova overiť všetky existujúce zariadenia a kontakty" - "Obnovte svoju totožnosť iba vtedy, ak nemáte prístup k inému prihlásenému zariadeniu a stratili ste kľúč na obnovenie." - "Ak nie ste prihlásení do žiadneho iného zariadenia a stratili ste kľúč na obnovenie, budete musieť znovu obnoviť svoju identitu, aby ste mohli pokračovať v používaní aplikácie. " - "Znovu nastavte svoju totožnosť v prípade, že ju nemôžete potvrdiť iným spôsobom" "Nepodarilo sa vybrať médium, skúste to prosím znova." "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa nahrať médiá, skúste to prosím znova." @@ -289,12 +283,6 @@ Dôvod: %1$s." "%1$d pripnutých správ" "Pripnuté správy" - "Áno, znovu nastaviť teraz" - "Tento proces je nezvratný." - "Naozaj chcete obnoviť svoje šifrovanie?" - "Zadajte…" - "Potvrďte, že chcete obnoviť svoje šifrovanie." - "Ak chcete pokračovať, zadajte heslo účtu" "Pripnuté správy" "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 cca5e5b12a..76176e2070 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -268,12 +268,6 @@ Anledning:%1$s." "Hallå, prata med mig på %1$s: %2$s" "%1$s Android" "Raseriskaka för att rapportera bugg" - "Dina kontouppgifter, kontakter, inställningar och chattlistor kommer bevaras" - "Du kommer att förlora din befintliga meddelandehistorik" - "Du måste verifiera alla dina befintliga enheter och kontakter igen" - "Återställ bara din identitet om du inte har tillgång till en annan inloggad enhet och du har tappat bort din återställningsnyckel." - "Om du inte är inloggad på någon annan enhet och du har tappat bort din återställningsnyckel måste du återställa din identitet för att fortsätta använda appen. " - "Återställ din identitet ifall du inte kan bekräfta på annat sätt" "Misslyckades att välja media, vänligen pröva igen." "Misslyckades att bearbeta media för uppladdning, vänligen pröva igen." "Misslyckades att ladda upp media, vänligen pröva igen." @@ -284,12 +278,6 @@ Anledning:%1$s." "%1$d Fästa meddelanden" "Fästa meddelanden" - "Ja, återställ nu" - "Denna process är irreversibel." - "Är du säker på att du vill återställa din kryptering?" - "Ange …" - "Bekräfta att du vill återställa din kryptering." - "Ange ditt kontolösenord för att fortsätta" "Fästa meddelanden" "Misslyckades att bearbeta media för uppladdning, vänligen pröva igen." "Kunde inte hämta användarinformation" 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 5a8ede8b04..d2c1032710 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -271,21 +271,9 @@ "Привіт, пишіть мені за адресою %1$s: %2$s" "%1$s Android" "Повідомити про ваду за допомогою Rageshake" - "Дані вашого облікового запису, контакти, налаштування й чати будуть збережені" - "Ви втратите свою наявну історію повідомлень" - "Вам доведеться підтвердити всі наявні пристрої та контакти знову" - "Скидайте ідентичність тільки якщо ви не маєте доступу до інших пристроїв в обліковому записі та втратили свій ключ відновлення." - "Якщо ви не увійшли на інших пристроях та втратили свій ключ відновлення, то вам доведеться скинути свою ідентичність, щоб продовжити використовувати застосунок. " - "Скиньте свою ідентичність, якщо не можете підтвердити іншим способом" "Не вдалося вибрати медіафайл, спробуйте ще раз." "Не вдалося обробити медіафайл для завантаження, спробуйте ще раз." "Не вдалося завантажити медіафайл, спробуйте ще раз." - "Так, скинути зараз" - "Цей процес незворотний." - "Ви впевнені, що хочете скинути шифрування?" - "Ввести…" - "Підтвердьте, що ви хочете скинути шифрування." - "Введіть пароль облікового запису, щоб продовжити" "Не вдалося обробити медіафайл для завантаження, спробуйте ще раз." "Не вдалося отримати дані користувача" "Заблокувати" 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 df039a5054..d5f82ed713 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -10,7 +10,7 @@ "关闭通知" "第 %1$d 页" "暂停" - "PIN 栏位" + "PIN 字段" "播放" "投票" "投票已结束" @@ -78,15 +78,18 @@ "好" "打开设置" "用其他方式打开" + "置顶" "快速回复" "引用" "回应" + "拒绝" "移除" "回复" "在消息列中回复" "报告错误" "举报内容" "重置" + "重置身份" "重试" "重试解密" "保存" @@ -106,7 +109,8 @@ "拍摄照片" "点按查看选项" "再试一次" - "查看来源" + "取消置顶" + "查看源码" "是" "关于" "可接受的使用政策" @@ -126,12 +130,16 @@ "解密错误" "开发者选项" "私聊" + "不再显示此内容" "(已编辑)" "编辑中" "* %1$s %2$s" "已启用加密" "输入 PIN 码" "错误" + "发生错误,可能无法收到新消息通知。请在设置中对通知进行故障排除。 + +原因:%1$s。" "所有人" "失败" "收藏" @@ -160,13 +168,14 @@ "没有结果" "无房间名" "离线" + "开源许可证" "或" "密码" "用户" "固定链接" "权限" "请稍候……" - "你确定要结束这个投票吗?" + "确定要结束这个投票吗?" "投票:%1$s" "总票数: %1$s" "结果将在投票结束后显示" @@ -185,7 +194,7 @@ "富文本编辑器" "房间" "房间名称" - "例如:你的项目名称" + "例如:项目名称" "保存的更改" "正在保存" "屏幕锁定" @@ -193,6 +202,7 @@ "搜索结果" "安全" "已读" + "发送至" "正在发送…" "发送失败" "已发送" @@ -214,7 +224,7 @@ "话题" "这个房间是关于什么的?" "无法解密" - "你无权访问此消息" + "无权访问此消息" "无法向一个或多个用户发送邀请。" "无法发送邀请" "解锁" @@ -225,26 +235,31 @@ "验证完成" "验证设备" "视频" - "语音留言" + "语音消息" "等待…" "正在等待解密密钥" "确认" "错误" "成功" "警告" - "您的更改尚未保存。确定要返回吗?" + "更改尚未保存,确定要返回吗?" "保存更改?" "创建固定链接失败" "%1$s 无法加载地图,请稍后再试。" "加载消息失败" "%1$s 无法访问您的位置,请稍后再试。" - "无法上传你的语音留言。" + "无法上传语音消息。" "找不到消息" "%1$s 没有权限访问您的位置。您可以在设置中启用位置权限。" "%1$s 没有权限访问您的位置。在下方启用位置权限。" "%1$s 没有权限访问您的麦克风。启用录制语音消息的权限。" "某些信息尚未发送" "抱歉,发生了错误" + "此加密消息的真实性无法在此设备上保证。" + "未加密。" + "由未知或已删除的设备加密。" + "由未经其所有者验证的设备加密。" + "由未经验证的用户加密。" "🔐️ 加入我 %1$s" "嗨!请通过 %1$s 与我联系:%2$s" "%1$s Android" @@ -252,6 +267,13 @@ "选择媒体失败,请重试。" "处理要上传的媒体失败,请重试。" "上传媒体失败,请重试。" + "按下消息并选择 “%1$s” 将其包含在此处。" + "固定重要消息,以便轻松发现它们" + + "%1$d 置顶消息" + + "置顶消息" + "置顶消息" "处理要上传的媒体失败,请重试。" "无法获取用户信息" "封禁" @@ -259,8 +281,12 @@ "封禁用户" "个人资料" "解封" - "你可以重新接收他们的消息。" + "可以重新接收他们的消息。" "解封用户" + "%1$s / %2$s" + "置顶消息 %1$s" + "正在加载消息…" + "查看全部" "聊天" "分享位置" "分享我的位置" diff --git a/plugins/src/main/kotlin/extension/locales.kt b/plugins/src/main/kotlin/extension/locales.kt index fcbfedf852..464aafd8a9 100644 --- a/plugins/src/main/kotlin/extension/locales.kt +++ b/plugins/src/main/kotlin/extension/locales.kt @@ -16,6 +16,7 @@ val locales = setOf( "in", "it", "ka", + "nl", "pl", "pt", "pt-rBR", diff --git a/screenshots/de/appnav.loggedin_LoggedInView_Day_2_de.png b/screenshots/de/appnav.loggedin_LoggedInView_Day_2_de.png index 5f2d01c7d1..29e54a9dcd 100644 --- a/screenshots/de/appnav.loggedin_LoggedInView_Day_2_de.png +++ b/screenshots/de/appnav.loggedin_LoggedInView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5864001f072e7dd159c5e4deab0196959299079306db6d4e3d5e8da3a0854ffc -size 37443 +oid sha256:360aff8fecec06ab71c718b988fb918042419f544bbd6911e35f2d4c5a2f5ba4 +size 43237 diff --git a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_de.png b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_de.png index ec3184aed8..d1858d5483 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4a78cf64b417764086669a053ca5c941c9566009c04d488900a5b245fdd2f78 -size 21138 +oid sha256:fedb2026fa21c863f5d1faf84e9928ddc0b5dc209d779e9972b913ad1f0b7b35 +size 24888 diff --git a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_de.png b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_de.png index 50fae9edd3..bf9fc73bf4 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21adf00b5f8e0cac8adb10a1d7717021ba51f795143d2785d6da2178d9306fbf -size 18818 +oid sha256:9c242f632e22731adbb94d346318537cb1b78d11ae8d47b1feab77d6e505aeb0 +size 21945 diff --git a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_de.png b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_de.png index 5d88c7383c..049b23ac7a 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd40cc933fe7c959bc13caee6c58fd72d71b8451db9aa03ea9f18919c989a078 -size 22144 +oid sha256:24f8bb681f32f95714485411e9f3941bd86294753fd308464e1db93903fd1ef3 +size 30023 diff --git a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_de.png b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_de.png index 04bcfc1b55..33a4efe845 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4afd8bd97b0405b9e3757244d8cf24ebcc0a0e13a65e61108b7305c48991b6b -size 33425 +oid sha256:602bee5b72f820db4bb4fcdae602a6c28709a7d82099d94e7b1836313202e287 +size 38593 diff --git a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_de.png b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_de.png index 3dd9fcac8e..beaa2960e4 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05c0a5f1867adb07d6b9172e9171e12cb7f9dd9803faf1e1585d39735b0b4f18 -size 21638 +oid sha256:6912024a1a3eb451a319e1dfcb7e4ec59480686ab131fa806792e081d43886b6 +size 21342 diff --git a/screenshots/de/features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_de.png b/screenshots/de/features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_de.png index 34cf9a062d..ee4aabb206 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c5b9b12aab39783104ba1c254146cff790fa4c9d138aad863aa01f5dea4894d -size 33616 +oid sha256:7c901dadde85e4a83140ea9ad61d2033f93fa06c6e1785514c7c2eb5f72a2f41 +size 39325 diff --git a/screenshots/de/features.messages.impl.actionlist_SheetContent_Day_11_de.png b/screenshots/de/features.messages.impl.actionlist_SheetContent_Day_11_de.png new file mode 100644 index 0000000000..0ad0f83bca --- /dev/null +++ b/screenshots/de/features.messages.impl.actionlist_SheetContent_Day_11_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16210ff9cc3c825e4ca62b7096e1b90937221f351bc3ba4e4f095c23823f8421 +size 51416 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png new file mode 100644 index 0000000000..bd8e14bc75 --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b62714a26902c5988014283a58014f3da0df923130fd205e0f8f58a5bf2fb1d +size 12270 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_de.png new file mode 100644 index 0000000000..f35713e7dd --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44f7d48161b556777535b16342e37f70903386470691aa48549eb8bae42bc4ef +size 9698 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_de.png new file mode 100644 index 0000000000..c8734317ec --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e14151400116f1244b5efe894e62a0efecfc6ecb89d795df3b863df9761621d0 +size 13313 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_de.png new file mode 100644 index 0000000000..f5875c7909 --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a72e722cd5d033389fd2ed6957c023e7e642ea7e0a69cb7bc8464eb0d01bda61 +size 13284 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_de.png new file mode 100644 index 0000000000..8dcfe397b5 --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:175fbc008939c2c2c725fcc0a968a2b3e06d2dbaa2151e7cb73652c73d67e510 +size 13280 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_de.png new file mode 100644 index 0000000000..d9a3df1826 --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93d4ed6e6240dd043a34f14e4927c2490e4459df5cee50c01d2aa020a96fe0b2 +size 13395 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_de.png new file mode 100644 index 0000000000..aecd7dd6a4 --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f28a49bbfeef2dfbbfe1e985e8e9b818a2faa82e99c033ab8db9783ae911ee70 +size 13430 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_de.png new file mode 100644 index 0000000000..5090aa2799 --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f97467b5e28fb8a6f020c69077c1d6c3577db04ce9c7ba038458e31aaee0aa4 +size 13338 diff --git a/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png new file mode 100644 index 0000000000..397a6d19e0 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2aae3904110436c4505edac81375d83ac42abf6aa873f1d738f5c96c13366f1c +size 41841 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png index 78a5f13540..dffcffdb8b 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b357015b5516a26a47b3e72636b0b23a78e3961017372c7ed12589313d00be7 -size 19598 +oid sha256:0730181922858ff0d22e4b898abd749fcae97cccb00057f7cb8d26d766508661 +size 20834 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_de.png b/screenshots/de/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_de.png new file mode 100644 index 0000000000..649002384f --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc29041f35950ced64d40ca04aaf824a66fe329d27be70893aa489498e50ff70 +size 37504 diff --git a/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_0_de.png b/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_0_de.png index b731d9654c..4215707ea4 100644 --- a/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_0_de.png +++ b/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c33d7b5f5c2eb70d8c67f715df11a1dc08f76a5874ec524db3015b56b2e75aaa -size 56141 +oid sha256:1ae931bb44942a78a2b2b303fd388aa2dc4570886ce460fec5356c6c9c501ae9 +size 56340 diff --git a/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_1_de.png b/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_1_de.png index e52536f976..013b5bedb5 100644 --- a/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_1_de.png +++ b/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80a90ae223b2db6ef8cc9a0b52689c6aaa200753ee5efc782e480262e0c006c8 -size 57088 +oid sha256:10bbd5a51d69ad431e6ec6e683c68c4013ea57a6173f86d139c0432374f71de4 +size 57279 diff --git a/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_2_de.png b/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_2_de.png new file mode 100644 index 0000000000..b2980abf49 --- /dev/null +++ b/screenshots/de/features.messages.impl.typing_MessagesViewWithTyping_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53c0538c910046975fdc30478b0c4b0cc0dae506ab57450b3fd5257582af9b39 +size 53314 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_0_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_0_de.png new file mode 100644 index 0000000000..70eec45a56 --- /dev/null +++ b/screenshots/de/features.messages.impl_MessagesView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afaf7fa054b08dab50812afdc48baa5315912274303227b4cdafd19d51c7bfc8 +size 57022 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png index 17746c958b..d554fb555c 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8eaaf78856243a79ca9a690d5086c7150364628546ede56372fafbbc7f3d67d1 -size 59309 +oid sha256:b0a3428681baec95d5b658add1e2594191293f2f3dc6333319036aa92357cc13 +size 59493 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png index 9ef066335c..42ba05797c 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57e4e00d2044083e4c851fe39a4be5da0fa9d54f535a4b8a47ed67abfb8299cf -size 47084 +oid sha256:844fb34d761f6cb5557940d7faec0994193eeae649b69850e190f74e1963a63b +size 47257 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_12_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_12_de.png new file mode 100644 index 0000000000..95e358af22 --- /dev/null +++ b/screenshots/de/features.messages.impl_MessagesView_Day_12_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a9e22c03f43cfa54502401ca4b7ca33e32bac330506ea565cc076d314f4cd6b +size 57055 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_13_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_13_de.png new file mode 100644 index 0000000000..e58b69d861 --- /dev/null +++ b/screenshots/de/features.messages.impl_MessagesView_Day_13_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e05dbc49ff614d8012f3e57bbafce0cf295e59834fe1bd404b91a2de957199a9 +size 60307 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png new file mode 100644 index 0000000000..fce9f82cfc --- /dev/null +++ b/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5de3be46943ee2cd4b9bdef4ba91984f1650169edae99e43dfe3ad18c60f9c61 +size 56194 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png index d448b125bb..611cb460a7 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae733c65e0ebe554e6741b48f5b5b2c06fd05e4380b37cdaa827b07349d7951d -size 59978 +oid sha256:935accfc69846c17513c7d616aa0fd7d6d83b170750f53bc77ced0577fb961fe +size 60188 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png index 20fe3cecf5..a4a540c6dc 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a886fb07d1866fc6d0be8ac34cbac05930e98f8a994d666f87c2c9a4b01cb20 -size 54707 +oid sha256:4aea915c0fe707394fb6926af1185568065abed5c67db3401f3215d70aa6e4d1 +size 54872 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_5_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_5_de.png new file mode 100644 index 0000000000..e2a1b3314c --- /dev/null +++ b/screenshots/de/features.messages.impl_MessagesView_Day_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:19450e8105c8d473265e0ff2017acc5dc470e9c951fbbba565ce2d5032748626 +size 54894 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png index 67b3c9dce1..ca95eea672 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66d6532d4d0ca266c26260ffbdd69f9957743c11f3a5fd2cae118892f119f0b6 -size 53881 +oid sha256:e1d62efd4fe4f2f0e9631057ebcbed870ca68363aebe809f6e220921deee02e6 +size 54063 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png index 3143574e3f..b5bf2c1805 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:290669083f6b2ab605ccd5721f19052fcefacadaeeaaeed79439d9fcd3db14a1 -size 58696 +oid sha256:6854f9ddb36b7e6663775f7d7efc43afd901097c4dcc404ac24a8b6d388b90af +size 58862 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png index 0488159920..e5de9c2e48 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6869c19d03e795dcefc8056cdd267d24669ee8893394ab90b3952fccb7847bf4 -size 41557 +oid sha256:d527f62c93cc0664a5f5ed0a229f8998db0eef90e30124414cdc5c2937163012 +size 41748 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png index 67e2d5e9e0..b898bdaf11 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd6b605f377925ca0d0511e9d8a03c83aa00ff1236537577f32c4de0521ef57c -size 40841 +oid sha256:2dc62af08db4186c4f4ddfda06fdebae6a04fa6ea9f0c7daa241dc02cf82f3aa +size 41019 diff --git a/screenshots/de/features.preferences.impl.about_AboutView_Day_1_de.png b/screenshots/de/features.preferences.impl.about_AboutView_Day_1_de.png index a536bbcb87..4fed080382 100644 --- a/screenshots/de/features.preferences.impl.about_AboutView_Day_1_de.png +++ b/screenshots/de/features.preferences.impl.about_AboutView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b5727816f00d86c4de5719f872e38d352d72c20d725457d2bc314269d9458a3 -size 19334 +oid sha256:91088ecb93c69c3749b3e7cc5fa6692cfe209c4bf178e043aca86025331f377b +size 19226 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_11_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_11_de.png index 51b9f1c370..ab8448ce8e 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_11_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d9b2118ed6fa3940feab3c1645dca5517417dbd4672624f0264a63acae2c9a3 -size 68179 +oid sha256:5460e4879b0184c178681ba553f495e52e202bffb4bfdf4b22b8a104368ca1c1 +size 71624 diff --git a/screenshots/de/features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_de.png b/screenshots/de/features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_de.png index 78f6b04165..1a138d8dad 100644 --- a/screenshots/de/features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_de.png +++ b/screenshots/de/features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee3736842947f6cc60a432b6e116c281cace42c5c1cf8daed471f951884af89a -size 29424 +oid sha256:d3454f94b0c268b6aa4c311ec22221ae2a6aead5d955c4fc93886fc41750c359 +size 32881 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png new file mode 100644 index 0000000000..47b507ade4 --- /dev/null +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dfdf3c021f14f4e065d3fccb225558c41c68d73a9ce03fade1409b9abd22b13d +size 28429 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png new file mode 100644 index 0000000000..37cc4e9e0d --- /dev/null +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf0cc1be1261344e1e775aab9e33a5e72a0b7b1c07b7118ec3cf03dd7b1c86df +size 27325 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png new file mode 100644 index 0000000000..37cc4e9e0d --- /dev/null +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf0cc1be1261344e1e775aab9e33a5e72a0b7b1c07b7118ec3cf03dd7b1c86df +size 27325 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png new file mode 100644 index 0000000000..a7e9f5c992 --- /dev/null +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:005d321ea138e0f6161ae1964982a7bd77ad539af88fc377712a789458d2b928 +size 39887 diff --git a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png new file mode 100644 index 0000000000..405b450e89 --- /dev/null +++ b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ebdd281a030aa9200cc026abdbbb17ce55a43967a1efb8f8ee6b8e1394cde41 +size 63258 diff --git a/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_0_de.png b/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_0_de.png index 48d0bdaff9..ac2777ddc7 100644 --- a/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_0_de.png +++ b/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29704cff82c6ac8ea1715d1bee6f5af4bad32e58010e607a5dd6cc8e86e0e386 -size 35997 +oid sha256:606dc930ca39c4122cec891fe559d8fea929f550eba6dc71bee22630b8e98ed5 +size 40023 diff --git a/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_1_de.png b/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_1_de.png index f6ad7ff94d..bc9544615d 100644 --- a/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_1_de.png +++ b/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24d4939b2b02ade789ba49d9d4be57925ce99dd45aa9fbe69e7abdc91341ceaa -size 27654 +oid sha256:e5f7ca215102143db527bedfac670a4e7b8b276080238d5bbd52759fa21053d2 +size 27667 diff --git a/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_7_de.png b/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_7_de.png index 6193505370..6960a7c73a 100644 --- a/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_7_de.png +++ b/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ede9337cf7a34bdc5a2bd8277d5c17eb1f5df3960b1a32174a36a2f82c57060 -size 33304 +oid sha256:06a3ab48b23ddfe6f14e5fcb3579aab09b748d8c78b154560562e0086a87b3ec +size 37426 diff --git a/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_8_de.png b/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_8_de.png index 0173d093b3..dc79192bd1 100644 --- a/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_8_de.png +++ b/screenshots/de/features.verifysession.impl_VerifySelfSessionView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d6b7ee0084f82268645d2927af5488d9420b490cdd00c8749611163399ff617 -size 27877 +oid sha256:cb87ec263ba5661bb7e89f4232eb96005da725a91ab41d53f19592ab4abd3be5 +size 30430 diff --git a/screenshots/de/libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_de.png b/screenshots/de/libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_de.png new file mode 100644 index 0000000000..7d6e76a5a1 --- /dev/null +++ b/screenshots/de/libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5cccd631341a1b87074370f3199f57aaf46a0eaa59897c67a0a4952a851bcbd0 +size 11168 diff --git a/screenshots/de/libraries.designsystem.components.dialogs_AlertDialog_Day_0_de.png b/screenshots/de/libraries.designsystem.components.dialogs_AlertDialog_Day_0_de.png new file mode 100644 index 0000000000..7dd8a7f434 --- /dev/null +++ b/screenshots/de/libraries.designsystem.components.dialogs_AlertDialog_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e3b1645e87780de02cc55498e57f9b0e4e5dba8b312ec4be3ff89573fc41fbd +size 8359 diff --git a/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_de.png b/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_de.png index 7842028999..2148458c6d 100644 --- a/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_de.png +++ b/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27b5de4266b4c718ddb7a9bc735cb3de8220a34d18d139407fe43008892cbb48 -size 13897 +oid sha256:5581fcae3d7d03cea15566e34c1cd605d2b0db27559bb7e7b16ae11ff5be9e3a +size 13271 diff --git a/screenshots/de/libraries.roomselect.impl_RoomSelectView_Day_5_de.png b/screenshots/de/libraries.roomselect.impl_RoomSelectView_Day_5_de.png index 3e6bd8573f..9f9a4d518e 100644 --- a/screenshots/de/libraries.roomselect.impl_RoomSelectView_Day_5_de.png +++ b/screenshots/de/libraries.roomselect.impl_RoomSelectView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5efadba071167b8bec80c042287b98de468824d2c5a24a7db5ad31d3a4e0e86e -size 28655 +oid sha256:a0a98d8cddf30b1ec29e768e6694adc863b5484f256982d585b6d47f3dbee4f2 +size 29162 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 0545934f70..338273e743 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,40 +1,42 @@ // 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",19944,], -["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19944,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19951,], +["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19951,], ["features.invite.impl.response_AcceptDeclineInviteView_Day_0_en","features.invite.impl.response_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19944,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19944,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19944,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19944,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19951,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19951,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19951,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19951,], ["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_4_en","features.login.impl.accountprovider_AccountProviderView_Night_4_en",0,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19944,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19944,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19944,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19944,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19944,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19944,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19944,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19944,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19944,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19944,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19944,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19944,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19951,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19951,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19951,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19951,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19951,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19951,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19951,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19951,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",19954,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",19954,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19951,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19951,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19951,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19951,], ["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",19944,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",19951,], ["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",19944,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",19951,], ["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",19944,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",19951,], ["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",19944,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19951,], ["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,], @@ -44,11 +46,11 @@ 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","",19944,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19944,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19944,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19944,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19944,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",19951,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19951,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19951,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19951,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19951,], ["libraries.designsystem.components.avatar_Avatar_Avatars_0_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_10_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_11_en","",0,], @@ -128,13 +130,13 @@ export const screenshots = [ ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], ["libraries.designsystem.components_BigCheckmark_Day_0_en","libraries.designsystem.components_BigCheckmark_Night_0_en",0,], ["libraries.designsystem.components_BigIcon_Day_0_en","libraries.designsystem.components_BigIcon_Night_0_en",0,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19944,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19944,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19944,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19944,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19944,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19944,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19944,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19951,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19951,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19951,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19951,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19951,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19951,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19951,], ["libraries.designsystem.components_BloomInitials_Day_0_en","libraries.designsystem.components_BloomInitials_Night_0_en",0,], ["libraries.designsystem.components_BloomInitials_Day_1_en","libraries.designsystem.components_BloomInitials_Night_1_en",0,], ["libraries.designsystem.components_BloomInitials_Day_2_en","libraries.designsystem.components_BloomInitials_Night_2_en",0,], @@ -145,84 +147,84 @@ export const screenshots = [ ["libraries.designsystem.components_BloomInitials_Day_7_en","libraries.designsystem.components_BloomInitials_Night_7_en",0,], ["libraries.designsystem.components_Bloom_Day_0_en","libraries.designsystem.components_Bloom_Night_0_en",0,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19944,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19944,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19944,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19944,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19944,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19951,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19951,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19951,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19951,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19951,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_0_en","features.call.impl.ui_CallScreenPipView_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_1_en","features.call.impl.ui_CallScreenPipView_Night_1_en",0,], ["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,], -["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19944,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19944,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19944,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19944,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19944,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19944,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19944,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19944,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19944,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19944,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19944,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19951,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19951,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19951,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19951,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19951,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19951,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19951,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19951,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19951,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19951,], ["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",19944,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19944,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",19951,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19951,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19944,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19951,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], ["libraries.textcomposer.components_ComposerOptionsButton_Day_0_en","libraries.textcomposer.components_ComposerOptionsButton_Night_0_en",0,], ["libraries.designsystem.components.avatar_CompositeAvatar_Avatars_en","",0,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19944,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19944,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19951,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19951,], ["features.preferences.impl.developer.tracing_ConfigureTracingView_Day_0_en","features.preferences.impl.developer.tracing_ConfigureTracingView_Night_0_en",0,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19944,], -["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19944,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19951,], +["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19951,], ["libraries.designsystem.components.dialogs_ConfirmationDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ConfirmationDialog_Day_0_en","libraries.designsystem.components.dialogs_ConfirmationDialog_Night_0_en",0,], ["features.networkmonitor.api.ui_ConnectivityIndicatorView_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicatorView_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19944,], -["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19944,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19944,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19944,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19944,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19944,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19944,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19944,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19944,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19944,], -["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19944,], -["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19944,], -["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19944,], -["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19944,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19944,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19944,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19951,], +["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19951,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19951,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19951,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19951,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19951,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19951,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19951,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19951,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19951,], +["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19951,], +["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19951,], +["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19951,], +["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19951,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19951,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19951,], ["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",19944,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19944,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19944,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",19951,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19951,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19951,], ["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",19944,], -["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19944,], -["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19944,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19944,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19944,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19944,], -["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19944,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",19951,], +["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19951,], +["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19951,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19951,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19951,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19951,], +["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19951,], ["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,], @@ -234,12 +236,12 @@ export const screenshots = [ ["libraries.designsystem.text_DpScale_1_0f__en","",0,], ["libraries.designsystem.text_DpScale_1_5f__en","",0,], ["libraries.designsystem.theme.components_DropdownMenuItem_Menus_en","",0,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19944,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19944,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19944,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19944,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19944,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19944,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19951,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19951,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19951,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19951,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19951,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19951,], ["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,], @@ -249,10 +251,10 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiPicker_Night_0_en",0,], -["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19944,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19944,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19944,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19944,], +["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19951,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19951,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19951,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19951,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], ["libraries.designsystem.theme.components_FilledButtonLargeLowPadding_Buttons_en","",0,], @@ -263,15 +265,15 @@ export const screenshots = [ ["libraries.designsystem.theme.components_FloatingActionButton_Floating Action Buttons_en","",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19944,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19944,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19944,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19951,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19951,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19951,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_0_en","features.messages.impl.forward_ForwardMessagesView_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_1_en","features.messages.impl.forward_ForwardMessagesView_Night_1_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_2_en","features.messages.impl.forward_ForwardMessagesView_Night_2_en",0,], -["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19944,], -["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19944,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19951,], +["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19951,], ["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,], @@ -298,37 +300,37 @@ 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",19944,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",19951,], ["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",19944,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",19951,], ["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",19944,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",19951,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19944,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19951,], ["features.joinroom.impl_JoinRoomView_Day_0_en","features.joinroom.impl_JoinRoomView_Night_0_en",0,], ["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",0,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19944,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19944,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19944,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19944,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19944,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19944,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19944,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19944,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19944,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19951,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19951,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19951,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19951,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19951,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19951,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19951,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19951,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19951,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["libraries.designsystem.components_LabelledOutlinedTextField_Day_0_en","libraries.designsystem.components_LabelledOutlinedTextField_Night_0_en",0,], ["libraries.designsystem.components_LabelledTextField_Day_0_en","libraries.designsystem.components_LabelledTextField_Night_0_en",0,], ["features.leaveroom.api_LeaveRoomView_Day_0_en","features.leaveroom.api_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19944,], -["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19944,], -["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19944,], -["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19944,], -["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19944,], -["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19944,], +["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19951,], +["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19951,], +["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19951,], +["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19951,], +["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19951,], +["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19951,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], @@ -379,28 +381,28 @@ 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",19944,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19944,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19944,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19944,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19951,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19951,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19951,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19951,], ["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",19944,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19944,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19944,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19944,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19944,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19944,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19944,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19944,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19944,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19944,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19944,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19944,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19944,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19944,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19944,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",19951,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19951,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19951,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19951,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19951,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19951,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19951,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19951,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19951,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19951,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19951,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19951,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19951,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19951,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19951,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19944,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19951,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en","libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_0_en","libraries.matrix.ui.components_MatrixUserHeader_Night_0_en",0,], @@ -410,7 +412,7 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_10_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19944,], +["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19951,], ["libraries.mediaviewer.api.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_5_en","",0,], @@ -420,10 +422,10 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_9_en","",0,], ["libraries.designsystem.theme.components_MediumTopAppBar_App Bars_en","",0,], ["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,], -["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19944,], +["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19951,], ["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",19944,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",19951,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_10_en","features.messages.impl.timeline.components_MessageEventBubble_Night_10_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_11_en","features.messages.impl.timeline.components_MessageEventBubble_Night_11_en",0,], @@ -440,6 +442,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_8_en","features.messages.impl.timeline.components_MessageEventBubble_Night_8_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_9_en","features.messages.impl.timeline.components_MessageEventBubble_Night_9_en",0,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",19954,], ["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,], @@ -447,26 +450,26 @@ 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.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19944,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19944,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",0,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",0,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19944,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19944,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",0,], -["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",0,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",0,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19944,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19944,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19944,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",0,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19944,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19944,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19944,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19944,], -["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19944,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19951,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19951,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",19954,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19954,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19951,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19951,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19954,], +["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",19954,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",19954,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19951,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19951,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19951,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19954,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19951,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19951,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19951,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19951,], +["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19951,], ["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",19944,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",19951,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -475,28 +478,28 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple selection List item - selection in trailing content_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple selection List item - selection in supporting text_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple selection List item - no selection_List items_en","",0,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19944,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19944,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19944,], -["features.login.impl.oidc.webview_OidcView_Day_0_en","features.login.impl.oidc.webview_OidcView_Night_0_en",0,], -["features.login.impl.oidc.webview_OidcView_Day_1_en","features.login.impl.oidc.webview_OidcView_Night_1_en",0,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19951,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19951,], +["libraries.oidc.impl.webview_OidcView_Day_0_en","libraries.oidc.impl.webview_OidcView_Night_0_en",0,], +["libraries.oidc.impl.webview_OidcView_Day_1_en","libraries.oidc.impl.webview_OidcView_Night_1_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19944,], -["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19944,], -["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19944,], -["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19944,], -["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19944,], +["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19951,], +["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19951,], +["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19951,], +["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19951,], +["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19951,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], @@ -511,57 +514,57 @@ export const screenshots = [ ["libraries.designsystem.components_PageTitleWithIconFull_Day_3_en","libraries.designsystem.components_PageTitleWithIconFull_Night_3_en",0,], ["libraries.designsystem.components_PageTitleWithIconFull_Day_4_en","libraries.designsystem.components_PageTitleWithIconFull_Night_4_en",0,], ["libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en","libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en",0,], -["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19944,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19944,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19944,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19944,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19944,], +["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19951,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19951,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19951,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19951,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19951,], ["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",19944,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19944,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19944,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19951,], ["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_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",0,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",19954,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",19954,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",19954,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",19954,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",19954,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",19954,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",19954,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",19954,], ["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",19944,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19944,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19944,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19944,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19944,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19951,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19951,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19951,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19951,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19951,], ["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",19944,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19944,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19944,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19944,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19944,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19944,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19944,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19944,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19944,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19944,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19944,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",19951,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19951,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19951,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19951,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19951,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19951,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19951,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19951,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19951,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19951,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19951,], ["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceDivider_Preferences_en","",0,], @@ -577,182 +580,188 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceTextLight_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19944,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19944,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19944,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19944,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19951,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19951,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19951,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19951,], ["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","",19944,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19944,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19944,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19944,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19944,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19944,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19944,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19944,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19944,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19944,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19944,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19944,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19944,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19944,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19944,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19944,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19944,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19944,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",19951,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19951,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19951,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19951,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19951,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19951,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19951,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19951,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19951,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19951,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19951,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19951,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19951,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19951,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19951,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19951,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19951,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19951,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19944,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19944,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19951,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19951,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19944,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19944,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19944,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19944,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19944,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19944,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19944,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19951,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19951,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19951,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19951,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19951,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19951,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19951,], ["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",19944,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19944,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19944,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19944,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19944,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19944,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19944,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19944,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19944,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19944,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19944,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19944,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19944,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19944,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19944,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19944,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19951,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19951,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19951,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19951,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19951,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19951,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",19954,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",19954,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",19954,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",19954,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",0,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",19954,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19951,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19951,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19951,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19951,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19951,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19951,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19951,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19951,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19951,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19951,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19944,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19951,], ["features.roomdetails.impl.components_RoomBadgeNegative_Day_0_en","features.roomdetails.impl.components_RoomBadgeNegative_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgeNeutral_Day_0_en","features.roomdetails.impl.components_RoomBadgeNeutral_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgePositive_Day_0_en","features.roomdetails.impl.components_RoomBadgePositive_Night_0_en",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",19944,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",19944,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19944,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19944,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19944,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19944,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19944,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19944,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19944,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19944,], -["features.roomdetails.impl_RoomDetails_0_en","",19944,], -["features.roomdetails.impl_RoomDetails_10_en","",19944,], -["features.roomdetails.impl_RoomDetails_11_en","",19944,], -["features.roomdetails.impl_RoomDetails_12_en","",19944,], -["features.roomdetails.impl_RoomDetails_1_en","",19944,], -["features.roomdetails.impl_RoomDetails_2_en","",19944,], -["features.roomdetails.impl_RoomDetails_3_en","",19944,], -["features.roomdetails.impl_RoomDetails_4_en","",19944,], -["features.roomdetails.impl_RoomDetails_5_en","",19944,], -["features.roomdetails.impl_RoomDetails_6_en","",19944,], -["features.roomdetails.impl_RoomDetails_7_en","",19944,], -["features.roomdetails.impl_RoomDetails_8_en","",19944,], -["features.roomdetails.impl_RoomDetails_9_en","",19944,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19944,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19944,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19944,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19944,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19944,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19944,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19944,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19944,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19944,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19944,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19944,], -["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19944,], -["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19944,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",19951,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",19951,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19951,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19951,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19951,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19951,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19951,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19951,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19951,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19951,], +["features.roomdetails.impl_RoomDetails_0_en","",19951,], +["features.roomdetails.impl_RoomDetails_10_en","",19951,], +["features.roomdetails.impl_RoomDetails_11_en","",19951,], +["features.roomdetails.impl_RoomDetails_12_en","",19951,], +["features.roomdetails.impl_RoomDetails_1_en","",19951,], +["features.roomdetails.impl_RoomDetails_2_en","",19951,], +["features.roomdetails.impl_RoomDetails_3_en","",19951,], +["features.roomdetails.impl_RoomDetails_4_en","",19951,], +["features.roomdetails.impl_RoomDetails_5_en","",19951,], +["features.roomdetails.impl_RoomDetails_6_en","",19951,], +["features.roomdetails.impl_RoomDetails_7_en","",19951,], +["features.roomdetails.impl_RoomDetails_8_en","",19951,], +["features.roomdetails.impl_RoomDetails_9_en","",19951,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19951,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19951,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19951,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19951,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19951,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19951,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19951,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19951,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19951,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19951,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19951,], +["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19951,], +["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19951,], ["features.roomlist.impl.components_RoomListContentView_Day_2_en","features.roomlist.impl.components_RoomListContentView_Night_2_en",0,], -["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19944,], -["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19944,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19944,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19944,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19944,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19944,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19944,], +["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19951,], +["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19951,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19951,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19951,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19951,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19951,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19951,], ["features.roomlist.impl.search_RoomListSearchContent_Day_0_en","features.roomlist.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19944,], -["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19944,], -["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19944,], +["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19951,], +["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19951,], +["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19951,], ["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",0,], -["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19944,], -["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19944,], -["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19944,], -["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19944,], -["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19944,], -["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19944,], -["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19944,], +["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19951,], +["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19951,], +["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19951,], +["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19951,], +["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19951,], +["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19951,], +["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19951,], ["features.roomlist.impl_RoomListView_Day_8_en","features.roomlist.impl_RoomListView_Night_8_en",0,], -["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19944,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19944,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19944,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19944,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19944,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19944,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19944,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19944,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19944,], +["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19951,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19951,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19951,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19951,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19951,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19951,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19951,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19951,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19951,], ["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19944,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19944,], -["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19944,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19951,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19951,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19951,], ["libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Day_0_en","libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Night_0_en",0,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19944,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19944,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19944,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19944,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19944,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19944,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19944,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19944,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19944,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19951,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19951,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19951,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19951,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19951,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19951,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19951,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19951,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19951,], ["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_9_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19944,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19944,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19944,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19944,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19944,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19944,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19944,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19944,], -["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19944,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19944,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19944,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19944,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19944,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19944,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19944,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19951,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19951,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19951,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19951,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19951,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19951,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19951,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19951,], +["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19951,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19951,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19951,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19951,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19951,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19951,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19951,], ["features.roomlist.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.roomlist.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_0_en","features.roomlist.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_10_en","features.roomlist.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -775,10 +784,10 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_26_en","features.roomlist.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_27_en","features.roomlist.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_28_en","features.roomlist.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19944,], -["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19944,], -["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19944,], -["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19944,], +["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19951,], +["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19951,], +["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19951,], +["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19951,], ["features.roomlist.impl.components_RoomSummaryRow_Day_3_en","features.roomlist.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_4_en","features.roomlist.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_5_en","features.roomlist.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -786,64 +795,64 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_7_en","features.roomlist.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_8_en","features.roomlist.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_9_en","features.roomlist.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19944,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19944,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19944,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19951,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19951,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19951,], ["appicon.element_RoundIcon_en","",0,], ["appicon.enterprise_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",19944,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19944,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19944,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",19951,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19951,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19951,], ["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","",19944,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search views_en","",19951,], ["libraries.designsystem.theme.components_SearchBarActiveWithQueryNoBackButton_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithQuery_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarInactive_Search views_en","",0,], -["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19944,], -["features.createroom.impl.components_SearchSingleUserResultItem_en","",19944,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19944,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19944,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19944,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19944,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19944,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19944,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19944,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19944,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19944,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19944,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19944,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19944,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19944,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19944,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19944,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19944,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19944,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19944,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19944,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19944,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19944,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19944,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19944,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19944,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19944,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19944,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19944,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19944,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19944,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19944,], +["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19951,], +["features.createroom.impl.components_SearchSingleUserResultItem_en","",19951,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19951,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19951,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19951,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19951,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19951,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19951,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19951,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19951,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19951,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19951,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19951,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19951,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19951,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19951,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19951,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19951,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19951,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19951,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19951,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19951,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19951,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19951,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19951,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19951,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19951,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19951,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19951,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19951,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19951,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19951,], ["libraries.matrix.ui.components_SelectedRoom_Day_0_en","libraries.matrix.ui.components_SelectedRoom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoom_Day_1_en","libraries.matrix.ui.components_SelectedRoom_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en","libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUser_Day_0_en","libraries.matrix.ui.components_SelectedUser_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19944,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19944,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19944,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19944,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19944,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19951,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19951,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19951,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19951,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19951,], ["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,], @@ -853,37 +862,38 @@ 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.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19944,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19944,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19944,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19944,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19944,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19944,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19951,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19951,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19951,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19951,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19951,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19951,], ["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",19944,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",19951,], ["features.messages.impl.timeline.components.reactionsummary_SheetContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_SheetContent_Night_0_en",0,], ["features.messages.impl.actionlist_SheetContent_Day_0_en","features.messages.impl.actionlist_SheetContent_Night_0_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19944,], +["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19951,], +["features.messages.impl.actionlist_SheetContent_Day_11_en","features.messages.impl.actionlist_SheetContent_Night_11_en",19954,], ["features.messages.impl.actionlist_SheetContent_Day_1_en","features.messages.impl.actionlist_SheetContent_Night_1_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19944,], -["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19944,], -["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19944,], -["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19944,], -["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19944,], -["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19944,], -["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19944,], -["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19944,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19944,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19944,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19944,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19944,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19944,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19944,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19944,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19944,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19944,], +["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19951,], +["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19951,], +["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19951,], +["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19951,], +["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19951,], +["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19951,], +["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19951,], +["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19951,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19951,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19951,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19951,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19951,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19951,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19951,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19951,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19951,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19951,], ["libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en",0,], ["libraries.designsystem.components.list_SingleSelectionListItemCustomFormattert_Single selection List item - custom formatter_List items_en","",0,], @@ -892,7 +902,7 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single selection List item - no selection, supporting text_List items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single selection List item - no selection_List items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19944,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19951,], ["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,], @@ -902,36 +912,36 @@ export const screenshots = [ ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], ["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",0,], -["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19944,], +["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19951,], ["features.location.api_StaticMapView_Day_0_en","features.location.api_StaticMapView_Night_0_en",0,], ["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",19944,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",19951,], ["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_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19944,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19944,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19944,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19944,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19944,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19944,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19944,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19951,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19951,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19951,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19951,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19951,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19951,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19951,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], ["libraries.designsystem.theme.components_TextFieldDark_TextFields_en","",0,], @@ -943,38 +953,43 @@ export const screenshots = [ ["libraries.designsystem.theme.components_TextFieldValueTextFieldDark_TextFields_en","",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19944,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19944,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19944,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19951,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19951,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19951,], ["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",19944,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19944,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",19951,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19951,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en",0,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en",0,], ["features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en",0,], ["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_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19944,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19951,], ["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",19944,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19944,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19944,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",19951,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19951,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19951,], ["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,], +["features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en",0,], ["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",19944,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19944,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19944,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19951,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19951,], +["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_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19951,], ["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",19944,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19944,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",19951,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19951,], ["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,], @@ -983,36 +998,36 @@ 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",19944,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19951,], ["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",19944,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19951,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19944,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19951,], ["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_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19944,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19944,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19951,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19951,], ["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_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",19944,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",19951,], ["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",19944,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19944,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19944,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19944,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19944,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19951,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19951,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19951,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19951,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19951,], ["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",19944,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19944,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",19951,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19951,], ["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",19944,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",19951,], ["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,], @@ -1021,8 +1036,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",19944,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19944,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",19951,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19951,], ["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,], @@ -1034,7 +1049,7 @@ 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",19944,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",19951,], ["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,], @@ -1056,79 +1071,80 @@ 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_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19944,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",19954,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19951,], ["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",19944,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19944,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19944,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19944,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19944,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19944,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19944,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19951,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19951,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19951,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19951,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19951,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19951,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19951,], ["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",19944,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",19951,], ["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",19944,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",19951,], ["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",19944,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",19951,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.theme.components_TopAppBar_App Bars_en","",0,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19944,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19944,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19944,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19944,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19944,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19944,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19944,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19944,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19951,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19951,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19951,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19951,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19951,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19951,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19951,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19951,], ["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",19944,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19944,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19944,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19944,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19944,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19944,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",19951,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19951,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19951,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19951,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19951,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19951,], ["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","",19944,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",19951,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19944,], -["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19944,], -["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19944,], -["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19944,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19951,], +["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19951,], +["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19951,], +["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19951,], ["features.createroom.impl.components_UserListView_Day_3_en","features.createroom.impl.components_UserListView_Night_3_en",0,], ["features.createroom.impl.components_UserListView_Day_4_en","features.createroom.impl.components_UserListView_Night_4_en",0,], ["features.createroom.impl.components_UserListView_Day_5_en","features.createroom.impl.components_UserListView_Night_5_en",0,], ["features.createroom.impl.components_UserListView_Day_6_en","features.createroom.impl.components_UserListView_Night_6_en",0,], -["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19944,], +["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19951,], ["features.createroom.impl.components_UserListView_Day_8_en","features.createroom.impl.components_UserListView_Night_8_en",0,], -["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19944,], +["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19951,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], ["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",0,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19944,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19944,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19944,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19944,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19944,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19944,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19944,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19944,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19944,], -["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19944,], -["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19944,], -["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19944,], -["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19944,], -["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19944,], -["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19944,], -["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19944,], -["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19944,], -["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19944,], -["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19944,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19951,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19951,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19951,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19951,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19951,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19951,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19951,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19951,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19951,], +["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19951,], +["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19951,], +["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19951,], +["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19951,], +["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19951,], +["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19951,], +["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19951,], +["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19951,], +["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19951,], +["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19951,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,], @@ -1142,12 +1158,12 @@ export const screenshots = [ ["libraries.textcomposer.components_VoiceMessageRecorderButton_Day_0_en","libraries.textcomposer.components_VoiceMessageRecorderButton_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessageRecording_Day_0_en","libraries.textcomposer.components_VoiceMessageRecording_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessage_Day_0_en","libraries.textcomposer.components_VoiceMessage_Night_0_en",0,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19944,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19944,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19944,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19944,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19944,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19951,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19951,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19951,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19951,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19951,], ["libraries.designsystem.components.media_WaveformPlaybackView_Day_0_en","libraries.designsystem.components.media_WaveformPlaybackView_Night_0_en",0,], -["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19944,], +["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19951,], ["libraries.designsystem.ruler_WithRulers_Day_0_en","libraries.designsystem.ruler_WithRulers_Night_0_en",0,], ]; From fae13290eb51ecd001fe1545c5292ab5424d789f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 20 Aug 2024 09:24:21 +0200 Subject: [PATCH 127/186] Gradle update action: Use JDK 17 and skip early in forks. --- .github/workflows/gradle-wrapper-update.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index d35bace705..b75813c026 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -7,12 +7,18 @@ on: jobs: update-gradle-wrapper: runs-on: ubuntu-latest + # Skip in forks + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + name: Use JDK 17 + if: (github.event_name == 'pull_request' && github.event.pull_request.fork == null) || github.event_name == 'workflow_dispatch' + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' - name: Update Gradle Wrapper uses: gradle-update/update-gradle-wrapper-action@v1 - # Skip in forks - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: repo-token: ${{ secrets.GITHUB_TOKEN }} target-branch: develop From 0269f868fea88469f73a97c2b2a8716bffb90fb1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 20 Aug 2024 09:31:29 +0200 Subject: [PATCH 128/186] Renovate: Disable gradle update. Update of gradle is done by a specific GitHub action. --- .github/renovate.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/renovate.json b/.github/renovate.json index 66e1b98aea..ca74a436e8 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -7,7 +7,8 @@ "PR-Dependencies" ], "ignoreDeps" : [ - "string:app_name" + "string:app_name", + "gradle" ], "packageRules" : [ { From abd1a51453c0b5d6e8fc2a099c16fdef1245194d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 20 Aug 2024 09:33:37 +0200 Subject: [PATCH 129/186] Update Gradle: ddd workflow_dispatch --- .github/workflows/gradle-wrapper-update.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index b75813c026..7cb6798ba5 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -1,6 +1,7 @@ name: Update Gradle Wrapper on: + workflow_dispatch: schedule: - cron: "0 0 * * *" From a748aa7b209b9131b3135e442ea48456f5a09156 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 20 Aug 2024 10:14:05 +0200 Subject: [PATCH 130/186] Update Gradle: add label `PR-Dependencies` to PR it creates. --- .github/workflows/gradle-wrapper-update.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index 7cb6798ba5..75c7330a02 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -23,3 +23,4 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} target-branch: develop + labels: PR-Build From 1fbb36eb72e8a1270906914a6306970011576b07 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 20 Aug 2024 10:25:36 +0200 Subject: [PATCH 131/186] Update Gradle: Change the token used by the action so workflows are triggered in the resulting PR --- .github/workflows/gradle-wrapper-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index 75c7330a02..975902e708 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -21,6 +21,6 @@ jobs: - name: Update Gradle Wrapper uses: gradle-update/update-gradle-wrapper-action@v1 with: - repo-token: ${{ secrets.GITHUB_TOKEN }} + repo-token: ${{ secrets.DANGER_GITHUB_API_TOKEN }} target-branch: develop labels: PR-Build From 719ca2621bccf80005ae1af35dda8cd0b0d76e86 Mon Sep 17 00:00:00 2001 From: gradle-update-robot Date: Tue, 20 Aug 2024 08:38:21 +0000 Subject: [PATCH 132/186] Update Gradle Wrapper from 8.9 to 8.10. Signed-off-by: gradle-update-robot --- gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- gradlew | 5 ++++- gradlew.bat | 2 ++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 zcmY+pRa6|n(lttO3GVLh?(Xh3xVuAe26uONcL=V5;I6?T_zdn2`Oi5I_gl9gx~lft zRjVKRp?B~8Wyrx5$mS3|py!Njy{0Wt4i%@s8v88pK z6fPNA45)|*9+*w5kcg$o)}2g}%JfXe6l9ig4T8ia3Hlw#3f^fAKW63%<~GZJd-0YA z9YjleCs~#Y?V+`#nr+49hhsr$K$k!lg}AZDw@>2j=f7t~5IW6#K|lAX7|^N}lJ)I!km`nrwx> z))1Es16__aXGVzQM0EC8xH+O!nqTFBg9Ci{NwRK*CP<6s`Gq(~#lqb(zOlh6ZDBK* zr$|NDj^s6VanrKa+QC;5>twePaexqRI%RO~OY075y?NN90I|f^(P# zF=b>fZ73b5JzD`#GC3lTQ_B3lMeBWgQUGYnFw*HQC}^z{$6G4j(n4y-pRxPT(d2Wgb%vCH(?+t&Pj z)QM`zc`U`+<~D+9E{4Uj2kc#*6eZMU$4Oj6QMfA^K!rbl`iBix=2sPrs7j@aqIrE zTaZJ2M09>rp$mgyUZ!r2$UK{+DGqgl`n;*qFF~M(r#eh`T{MO?2&j?xgr8FU$u3-` zhRDc_I23LL4)K&xg$^&l-W=!Jp-P(_Ie07q>Je;QLxi8LaEc%;WIacJD_T69egF?7 z;I_Sg_!+qrur8$Hq4grigaiVF>U7uWJ@Hkd&%kmFnQN-P^fq0gB1|uRt!U#X;DnlV zo?yHWTw7g5B;#xxY`adhi4yZn@f(7-Xa(J6S=#d@&rlFw!qfvholE>MEb|VWn^g}G zMSrK&zQ^vDId&ojL!{%{o7?s{7;{+u%L{|tar(gp?Uxq3p?xAysB>0E$eG#$tvkk9 z2Q2gEP17{U6@UD*v({5MP-CTZfvWMItVjb4c;i~WLq&{?Q1(koX&vt7+$z}10{^Id z{KDjGi0JpD7@;~odF__0m|p;5rIrHidOP9^mwKe#-&JX-X@acc)06G{LO1Wu)#gvZ za~y9(fhA%UwkDOVU1LBJ`0ROE z4&)dJKK%mG@+CIm?+wt9f~@xIMr8}UH*K1j| z0pppo{7gv3v{URwxVMeg>Ps!L5IKxm zjac2egjgb0vH5i75$s|sY_RYec#>faqJk|AGgV;v=^%BM(^p{p;(^SVt-88G9f!q; z>p}9E4^f0=01S2pQBE4}9YqE%TV)*hlU^8k9{&=K76+*Ax^r=AkBb%OCP^P2nm0Ri z;D-|Zk?gGeU<12ti2CnPVNA(Pb)02+r|&yTWW-OJO7 zNLb0pps6aN?A~NJp5kj{{IOlf!5KWMleV@-hYLift)D>-7K+tgs=7Ake}oBnIy-y1 z(Hn@Hjw=_(x>dO5ysQsrnE%A*bk0K<-j{1Yqz@#n#jOL^AzCr#wR|WYzqk6i7v)Lf zkXdKxzuu20aP{Tbg$(+9&oh7cd(Uoqqf<#ujb$q4sZ~gxFbQfS zS)kNklyL*{2AELgjZ(LBu*>S(oH5AaJ;YiB@;l@=O%F6B?oanzoYRM^fQ9-<~^=3$H0g^JPMLQo@SZ@QuNvy)tyJ)LSj`+()#fy?{aV4Yg^7dlQ7AQM^3GLCR2dAFR zJjtfKiVqF`l-H_fz0HD|9g>)pOxn}k!vdZ=DO!7Sikm{Z%P6BrRkBS6W?ZB5W&7rT z@uYpf@M@a!z7H&o@-yrcCL^Ff3e7p3T`R9p?@o-acXmbTSa0>ZANzCSgovsd%;i$| zVus`not!oL#(W`L-!9w0jdaECaG4hk{V7IOs676ZquZH~0TX5hDq|)x z6T497l|E?f4)LA>j=S8}b$0LS=I4h|hUFJYJODT8Li@#6kF$k0)@*l{RnM1HQ%?VT ze-Pqlc!~t(oumVC*?5fwR;P6u{tHaZ~*LlD;B)4f? z?lpWfa2P@)g57flVl83Ej%P`2)gGyaPjhvD(%i~{`2b>#3!+y&` z!2nuwHMFA-zUY}f1^0B8<`N)Gr=A4TS@b1qykmd0Pq{?r)+1^^+D(=xasb^Tf!oK9 zBLL+*p6M_#ufgLzgq1zcSwZsZnQWFLC3`Yxdg-2=*tT`J9nrfYt)RF)YryBf8_gW{ zvKbB+oZLehfT)S#<|y1)E0hW^?+AnqPXq9Hu;v3dsMGdr{SVyF63;K<8VcgI#~}1i zLYSBL0K;RTT(;>2x=*!1Di9w0mwr;`CN}kM65|Ay{~z}_^JKOsRaN<~#9O^iiW<5P zYN7r~HV!#Nz~IZU`P>1Xe%4f~K}KcF#X&5kO*G}-)74S*tQ8CietdPcA1Yl;S=Mr# z`#MYY!{s^uo=jn7;k6O%(}fN+*0cWMpt~#n9DR<3NyU?+3D^AgI}S)Cu-Tljg`VY} zX1=fq$?8$DtOeGxE6f8lbS_6Q3C4+LDTO$}_IpM$Xv<|QSC%+Oll^q$y`7o@jD{dp zNDl|&X)r7wETa-#h*d`KXntxI(Y{vLha{$0i7@G8xx^m=c<{lJ9?p-i!^W{%j7-oo z0W^SzZ^(Wkyz*We{lEn%Yhu-ycUOHtrRiVJL4~&S91*D0MrLu}Q>v-Mc?GcWfpyz% zX|UvcN@krFO#@v|CtYM}g|=L3%aMo$E5<@CM%c*;?u>LOTz00@+dt1{yg1y=$h+{|D17U}$*^fE^H&8b431EUE z<9tv0V_#%#&1N#j7AKCj!tTK@J%oFW*ESW<(#Gl#Xs%v<@AitI?s92nLzm<)w3Wkkom1f$gcdUi%g_*jofy&}N#luL<$GVIe{iQkQ)sIHVy zBgItnPBFamrv6Kb{eE($Q(f`ZPeW!Hm%Y@F*OF1sKB{Yy|C>WEv_mfvv-N-jh)B-5 z4a!1WcT@9a+hGaBrc~sz=>G?Q!*Zp^JFRUvBMyNR1;`)j$RhH$6gEyVKhd$&K-CFT zXaWC-Y=fyOnqT84iMn9o5oLEOI(_3fk!W^8-74|q1QhQ|CmT0i=b;6Z3u?E{p7V{? z;f#Q-33!L+4&QQcZ~GAqu$NS{M;u%`+#9=7^Oa5PKvCCCWNG_~l(CidS!+xr-*gg{ z$UQ`_1tLT_9jB=Hckkwu>G{s0b0F4bnR7GibmHo?>TR&<3?D;5Fb#gd8*wYa$$~ar z7epl1qM)L{kwiNjQk}?)CFpNTd?0wAOUZ|gC{Ub|c-7h~+Rm(JbdoRe!RNVBQi!M8 z+~U6E2X&KSA*T6KJvsqwqZl#1&==Dm(#b^&VAKQ>7ygv*Fyr;)q9*^F@dCTg2g!w~ z%hg)UXAUyIpIbLXJv1nZX+a_C)BOH2hUim|>=JHCRf(!dtTidb&*~I!JrfRe+PO>w z@ox$G2a3i9d_N9J=|2$y2m-P&#PTNwe!oLBZFs;z|F5kXvBDn<)WwE0E3$ow=zg3R zK(9;sf0t;VEV3@gAg7jRtnj%-6O@!Hvg*;XcUAw}!=2*aErvB(eQIm(-UGmq^J=XN zTqJo$Y|WKo^HlBF3BXJrA#}7ZLg=r*w`I*~Ix`o&2k8^(0mt8Rp=A>F`&gehhp@Jy z^e^#B2!~$LvNCKugg)8)-G%&THdk~kfextilegP9?#C#()F59U$&eo(h|5>ceo*Em z{PEE79T$YP|Kr7K`WBHbtQwyxFkCl6xX&+oUf90B5xoi3_5KHHCyEE*oPbOQkfMz& z6^hT8_NXd2iWk{q9IKae1{_7hMPH8I7_BMtVOM4 z6jm?E0QJOn$qrgsJ`9w##GB9?G})-GXSQo6(tYS(Q0-Ct$co?Zzl0?NHsDRron?;_ zZZgQg)%XW>P?8_&zoGuF(>Och2kEJXsu1_X&~w87x!b z>~h!a>e7{`p@+#hXF88wI*JeWRZ;J4ev4<}HWf|Z;(7$E!S5l9wzBHFe>^I{2`a;a)QnAwa2xv1e(bq$<}!8o^ofGvYpk7dBR+`*%iE;hUY5 zaHF}OjGO9r*{%lmcK^uFiTHgoUD`^9Nx@~;Bg!V* zuuJ&ti{DQiq7RyJAR94wem{}cPK1J(Yxnn_{=>?USqz-~&QXRStS^s-7TksZ$AEI! z#og36s3JGtGU{CnDHRFtipFqvrE*gw7_K@NN0h+ItTq@4fqN!HeQU1y7*X?9+IfZT4Vxebpt z%#VzgdDK~-&+=Z*#>=n#XUhNvBZp3=Cr41jMqwJkHLf3L7Vm~V#GgJ(Jpii~PmJ#s zA7Ft!{xD@z>9DUb4JbiUBdNEcU4BO$651iN*mp*f)HbRRM`Cx5cR?5IfEcU{IZWwf zz(M6CDv)>xa3x}K6%tP^i15P1&&DOLK=k~+jNR$UK3frSl+|PjSC-dBItvD~LL! z>_g(YYdO4k(5EbPOw+v+;G7~jYm>F@Ai|o`gs%F)F8tDz$dl7Q%aCe|v|$UkAul_R zNlA-beBX^IJU?kgS`E$it7nF4DaI!SJAGq)2P&Few(-|tp z?K+%D3e4{pfkayrcbm0ftu6Ol2ZzdKM+4i!hNP3NRL`EvvZJ3yvNr2MV%igZ4kj``Qrdb_OI$7jWP z;l0DYf&0(-*QcP5zrP`HVznW+SbH63Qx$7_9~NjRNg7eKqI!UJ=XH`g^=t8GiFTu( z?2L{JKEu%jJx&XjNzU(*!ZNmL1@RlJA0G$2_LrAb_7lmjil(GSlSM zwTes`m+3R;3#N~Xg#9owh3ycXV8@ZlaY_16kpPFA={721b~URO4HD3sp%fmkZM}k) zZB0#)kP=RkNB~R-MCk8aljG_bagt4vIb~8)BV%(b8_;)&Kf9GX+%O_cNG|(D$!3&D zL(I8}*LqN5NntipFlN13=`D>6!{D@CFMBH0kW3=HccJV+xW~|$qeFR5i-2{X+iWMu zI2$gepQ)H_B%ip_BlWOQ*|pErXs|4ir{IHccgaIJ84irE{?+$KDABXr&f`jB^V-c% z$$u`uU1YB^{<+UN2cNg#7&0bz@yF?5>j|;)5&IV3wIQp58X#OE-M^$HdyvL|Um5t? zhZlAG!Mz%XkUe3t471JM*Yur}o30vzu6RN7gJyNcf!IItsDO730mcJ*O!~V``y5=3 zNJGp34DZ}wd1H6V`Uuy%es>BiO_aE-S8jzir#$& zyk)@2a5tP$@g%jW^b^JGdo)X@Q%sE`^lDQmY9m%uDFpPX`w9%=yQ+nneMm#OaXcD` z9}{tn5A2b2z9783vL2_jSao?uxJhWJoq%47*RafM4o0@gY(p)F>qT4^XM5GLzV#6j zC+HoGhAne7o_w{WUo(B++z7lU3Y0k1rYv9|TSv0vR-Du(5=VakbbelgZTeDn+a_Wv zq_j-^+Qz1WAl;Zg>ahX|CERbX1V%B!hTKN?M}fGoA07M(WU&NfT&TmN`P@56U2 z^)vLDs|Ln~0iTtn-?KTeQl@T&bskJFuTUS!m+$CS9vnd}8(UMO|Kv6TCfGN9NUu&4 zL{)GTxPq>fwsJ~aU=4Qhuq8*RzDsP(LZh$BHezq&9gK$IS<|DYbm})$QTGCS6T;Dr zEkLct!b+#<1r9OKG@P!f1wm8>=Nz!7OzJm!g<+`?N3;YaA3(P@EL=(sTaRMDD!c8=-XN^4BXp(eVkj$NmEMYPP>YJ4bJ3yUud z<3BeJAJ$6z^TuywnfH5lv#$lgwraNw{IV=tIznPH1DT`v-5yS=!)J<}xxl}uZf9azA2A97Haf!;<3y01hlw?dWNEv@TLi1s-mO4vmIT%O_42nS z$VRWrs9NngqRRkWAnWkn%`Rw@?wH|)7XL`EL5EZu$qyJW31&CB^T_)qwIv!{;E_6 zo-9XAryQRlk-O0>o#-SZO>|6OYq;}<*>Wu1AsVRiXY4f8qb;+sItv3AyS!4Ry+q}) zA!pAB|BmC;=RIOk^^vlsEH(!Q!7_1FK~ZB2err*o!+b(r=m1b?$6d!%zmN+69LXnT z&gRmM+n_R-F@sT*IYv0_mGPvur!u`iWbQO7SqiGFLeY&yga zf`lM&B74FA2C?N@8_z652fjhBEoDUKbP8hL{0{HAF%qDo7)o3=3rg#6)T7%%5^wl% z9R0*S*<~>nzYOdQk2l`9h#t+gJy_xujw6xjV(8S<_DbVg61&pT%Hi42l%D73G?adn znB%UdNM0p}lEF-P2%TAMam2zpQev71e>a$$%i+r~b+D9G9pF|oY_*(-u*89oKsXLY+UIbqq)MQ%(GYS{(*n_S_*RN$*~`zUtab%0aKwhx znc)Yo?{xq1sJCgQD)TeTci1ucvbez9q=A72H(-SB18Kl&6^vHV8^i!p@>iF!DIw17 z+8Q)TNisB7>pwyww4y)yJx*wX6SJO78eLBC-ar1+k$Z9fy;wBD|3kzI{<+l*>PSY^ z_?nLOZaeWbU@C3hfK?X;Di*8CHCPkx2qco6(ZyJdqSzp^TJ_5Lpa0UP{Gy+!b0Lr% z@xYxSjUKoY6L#>$qx~KD$-0=|OF7zhVP~ntMgEALYPIfhj@+ z!;JJ7te>CcovruwHsJH6Lta$nm|%^C@=V-rmhU{+I~0(|XHQ9jt@L7pb{gx#{4r!) zg($FyFTslcgu(~6lYr$nW?)%*l#VJ=R-jxK(x=t1bWlu(nL66T#qj%3aZ@uVhy}Co zDU_q61DD5FqqJ*#c|(M5tV)XBN?Ac^12*q)VN4yKPJ|#==S_`_QD9|0ls!`2)SwuHDRA_OfXQDq3%qW&MZB}Z!=k-9xqev8jHz(H z{^D@cIB~QiK>~wa)A&^Ll^Wi6QgCzU;iv-BHsLBs zH7=jN%|>0S`SjP%M&AF1PNVDp_FZ?2Bm@7`DC&v(pYrw!!yD#4 z6+<=HS0Ln6MhoKxF<%~H`y20{vf#pxh=;j{zY381gvAFekgG|>G1zo8$&az{V=;JR zy_puF4$L$?EMhT?;TpQoR*j16ll`#AS4e96C}yp_aGKkBe?1H|k_;gG-~Xorc<;lI zkB}fB{$c-D2mGA&{rm<*@F5)c3X+6??g~XoEwuzSuch0D@W~P5(2I8v8F$c2$Vw51 zP#YLSBDqtWW^EYBl^QYHF+MA7am6f4DOhwnJM=W9$uvMOsZ%_~?)2C#wb?CkI$7{K zEi)=#|5pFvg^){zK5kpBLjB2kZ+$ZB|L=W|aNwyyb(gC2l7bcpx{E-H@)q6@D6N^xh`{1E%ItF2$eeB_SjI@b2WgTpS1thwg&n`jiIzw^TtXUyB{00($GIq>vbj|}bav}}Q_~wp3>k8!E@hVC;OMUTu|= zAy#vXH*GrUHu7^cNZWe1>y;2(51js9wbu+R3Aa*(wzH9+X0dIsf&gc_x|_LP z>~CF^?(~U}+l~ehe|i>?4eo!xkq&Lk+RR-1duNP#o~>@1x)s&i&u zRaYL@+D&_M|JLI6fHbEr_`U;HgPTh#E3?sB)A$*gqyBgg*ql|a-m*TX5rACbWKCE6 zdeQ`v8m6>g^ugv`p|HY^#1QZrGGUj0^HVDc@{?Q0yhalbBEV{+|HzC^-{&e{5K%z9 z6Bxtnfu1!@Mp+Q&*&~;FOg&*Vm<@4b;{FG0-!UUXX!|)1w}op!B_|7_s~d(+=9Gba zKp8`LaB4D(H=cGcspJ_TjYaOwMb=sGn^gtUVhK!UI~2KKYEE-NC}F>+BEY7IVvy%KRvm00tg!Q`y=er}wpEetX}K@;}(}{s9AzV#q2@ zBy7}->|N?13POrs`;U?(qAG(I$~Gt+Rgw%aNZ_0fs_utVvRJT-7z4!@x36v@=NBX=IqkK{#Kg0w48de@?#Yb4M(Svj5=T+<ONr8-oh7l?Cji@+erqur zFhZ=9|Lk=$`c}v4u`)-!!UI=!9Jo@h&7p4RlS#u! zZ7-prn75JkV?VjptX;@$#`U`{vB!=Z?V`T*FBF>J?vsML7e6@2GbUteMFfX-TUu{2 zLNIG*;dV)8GV8gAgEf#)X3A>p3^CRka1v?~8x^anBhQ=L=LsOl=&pcOYHo98m##ye z34MtGCDK!`ptl?taGMr5q{!zVc? zG00e){TV?`YA9eB;(lA3lXI?RrB4BYQGk?vOmTIUJED=(`_*gtn2DB-t4WW54as*W zb2kD-lWX>lb$+W!VFakki>B^Vc+u$?NLF>)!U%b@Y}gYJ>m2H=^x0=nsE0TF^Yu0h ztgH8-o1%+jCk(+&`|)tTfEVHq0cMeFa{Uz)X$;fCq%Y=SOWML6bYfeP8j5hktL`KK z(18`XrUn&WN9PtFxh&dX`y~YBsmdhi7Kw%tKzM%^VEhdD<_XkulW-x=JN6OPbFI4@ zzDDRN+f=@{0h*MswwOqG6gJ?{NuHx(y-|FUGsxyZ*x0~$MW(eY>vqq4Fh#t7uzw=- zKB?|!0N~!h^AMdLa)oR!Ca#HZ9&Zf)ghuO<^RN)4twRlygHnQG(BE{cDc5E}OF4;xss6gYyV~EcJvJkX)xNWb=@yw!uq0v-sf^rvkp-;?DPWK@*SEw|V;IH=7 zfQqEV_>DjOPT~8X*J|H8=&RnzK4~S7ML~nLX^%s-Vqc^aWy7N$y57qciZGcqy#=zU zs8hcHiI=D$+RB{|62{ohCTiaML6FI4Uhzo5D{Jik@poCs0w7F)*w}F4r0sJ~#u-72 z5bK=ANt=M$Dh5NKnxGsg9NRR?WD-x|FhTwBjd zD<-K>44DB~i%frJOfnzh1R>PRY34kw!6~p3M$JLaD1r@`=h)~Ngks-(gdXh^Q?BTP zZ^Zj5w1AwtuR2$~E7s9iZdF}z%pv1em^V2rM{1tLUY@-+Sc0(9jA|iZWml1;v13=U zHf?y@#mb--7z6$ue>`qjhE~brk$AY-RG90~5wcBbDReXR2)pKg{L>;H(DI`U!MLNQ zY9rFJP@ZQ}jlcMh%WSCo%vf+nd0Gmd*F%KMIe>slCUh)8Ma|;M_I+v#;|ueg9oLg; zq2HtZX%&#F7vdpNlkX?}(C7dGC^y#NB#m4%69RzTNrk%4ol~hSI%>2r6B|*ZkW(*P z;u#s;+faHo{tfy+1L^RzWDi*^JR0iY(zJDB36y_QJ+|E-2x+cY z!V8uLNktH~q>WQZuY!Ap66WP|E!0PA1jK~)^8oJVGbspJs6QL!!-5Qm7 zHYI|_`Actg?vDzdg5{86w@GS$G6ANzff7->6i5pB$T4O}`fZ_;{217Om0gN5zTr12 z5mW{hCzCE-QubjxN$TAE-XgI-8dTY@OZmq`y+y_>dk*(qXF0{nam|q@~i}Utp*k{yurq(DW54hkDT4bbg z=_etM?Nf5W^o-HEu9_?&xEqPg^P^mTxLH8n%u$!mWvFG|{&)jtnU&6|5-`~eaNz0%D1BDo`{ zS1N5(KW5v^2eLdd_%`uaRndF@h0Uo6=M|8?b~KbOLZk{HXEnGmtgZXf2inI*1r%n! zQ3&%RI4r{f&dwW~HwH0Ked9b!k6{>_19H z_Ai>5IChDMY(FfMyG%;30?SQ{iV9KyGru62+Y)~qSQ91}b~}w<&*}R&1c#$O`H@~c z5)2S_eXx}M#N{MuGeQS9@#UJB@;W_j50b}jIhxMPloEFQZdvwxiU^RYycTzgK)-vl3LT&$L8~@68$C8~5_U{cR$E#w*x65(qw&eoL@>%ZHvj zWnEMlSh*(o&oy|J7eJ5OD`ssy%F?*Vp?`Cq;FShyl{ZoKCG5g{y}>usznni#8ki(i zO{w@n{iAj1_ooX@+s*!uW60WcH~*bNOT6z%0jVML5};wVrQp~`Uss_{cO2oud_nNA8^B$?07fJ6?iI)Q zuo9G)O-z)DqstrBqf>B%S05hf-wep0@$BFHKSrkZ{za3D)yVzRz)2{wf8(Wp+xyAM z$rtyx$gi3A=V~V!`Q3;BM0$>*VVtxEM|xDL^gew7ydy3Q6YzD&THRz*q33Ms_D;M- zbCx1Ft#UNB)V3bf`~{ImI72OTp^|bF8?G8#FRj+Biy8ET5#rA3sd|0FR@U(LAJ%w8 zS1%n8Z=Amhw)92rIsof=YVWF4jw&F*j1LG@-`+cR0-~2LqXRH8(Ccne{y#MCPncF64U`0uO zWmi$dlii~1D0rLR{qc|_2M!C$t8^=G7xQY)9!#Y331A|>N)EhmyVdLWL9I3YLJ`7? zZmpqUJB>Ni9oiL)^1IK1UoMyhWE{$9M2M6Xi zPKk7GpMsA6vjZbU7~i+u|J6Nk|Ci!Y3UMUT2|`M;JsNQACdJ%ooo9Yt{?A+0hMpxi znEa~~sxC>rKrU6bd=WRb;%wsH>A#j4{({&1GYSNR57Gama(3)2A;SM>qop}l>Jk2* zn1+C$fIxuwzg3mCU#SOqb-wOCb6mBcYlA5+mt<&_J~sBxc(GQtBFINUO~Mr7<-uu($>P HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ zF^}Ea+#Je`Xy6;#D0FPnSrR%Y!QGA~NA^{oWmW8C<3dr{x6wWQ{4+bzemqV5W$i5~ z=J0jXZ>uZb>DT@0Ks?4QJ{`z?8JWl3$y;2pj#$XP*pv$>$g(z43{YH9KmmR6<#sIn zA`#=0#sgycaBQ^&}Xba!|KaZ8~b30v~nLt z9%#gz_*=~KD{3t^X~l>480*}PhKN=??g`RV|4Ud{Gyyl187MJ}r(#e+H$GEdI+p1s zq_25h;fV)$EPK%Dw-(G=f`yHB-_tttsC!?k7*#!|4a>`Ahj8nm?&n>NRs%jkZW^3-0P_yMP5&*6a26{MRj1&TPF zyE#|c)5uUHzMWx=rMKpuPih*V=S;W3MzIZTw2uTbr}8`p2bm+Z6Sa%vvWAWSf4H)p(+ zSQ8;EvUa#wqWV+9vmIio(%7wukK2SwjUS8Yl%Rq%=~PU)2$Tvm6`1!r3H@U#_|bB0 zmlT1PS3wPB(b&^+@YY7Y$n4l3mV3-X0$>z|gZp6O*Lhzn&?Gad2ZCF;+#95-Y?#y+ z?*l@Yf=a4w{Px=o!N|3~_XKfk&G;fN>Ps&dp2FpA~qD=0~=!NOS@B#XAKKkND>Y{4>rqxrViKD7;?>j8`R` z&G)3FN|dfsxnaI^!d1G%=>AbTTxZWo;n-DLrQ!sj=f~VAOe5zhGS(dgx|!ls62fbX zV@<7Ck^!}R=`Swr?(7w1rY6Nmq~sfXJ?TiKJLn=&SQdEt9$@0 zA+h1Wbwbri0s-stc8yVq;mRa6@kEf8^KXUz&jcic!+avDvvJFa>k0ioWug=T3oPw; zyj4it&0@>_*uI@2=^+T7sL1_!^aJW@Xfo8aC#3^WtQC7fET8b9C} z*u^ue6Ojn z7@(eskJ2+cNnH9~VyfIh<-|7!je~vGy*odz(sk-u$~SrYF3glruZ*W`{sqnS+9=;Z zh{D@MSG91%lr&ua8%$sJF%y1I<|e;EdfJykY8#D$Hc_81n5`$7;1N|b0tvvPLzSg& zn7!5x?T*@rQUKcUhTIjV(rw*5oQYlm5DbEO?60#mohHfbR$3_x#+PZoYi@Vd4`#YgKyTd^!4n{fN~WZDY61sAOm6 zl!d^i*a01QxpWM9Pcl?&{RgO}uq%ErOk5WpECvnfEh!*YP&1Sl)uTN4hg??Vqs~i5 zYsfufz3?{TtwuBN=`0~Qg1PlWH#OGG$ zLLWU17$v``)CE1cds_7kj8mJ{-+l8{DS|zAQ&3|qpOY=!J|kXUhXue9|H>4gqk|n) z-i34GmxLFj8asb3D#D&=ya*a5`C<=o?G;Ev^LV%;l#nH#O=7Nh@z1Do>j6Q;I5S2P zhg|AZbC&|c7}uSJt57s2IK#rSWuararn-02dkptTjo*R{c5o(bWV}_k3BBnKcE|6l zrHl&ezUyw^DmaMdDFVn<8ZY=7_{u{uW&*F<7Al6};lD(u;SB=RpIwI)PTyL=e25h* zGi{lRT}snjbMK~IUx|EGonH+w;iC2Ws)x>=5_{5$m?K z5(*1jMn%u0V1Y%m@`YS3kskt~`1p(rA4uk;Cs!w^KL$w>MH)+cP6|XKr4FfHIATJH z!EGAK4N>1yFR`-zW|w%ByRe#=&kA&#WyUldDGpt!wf-8SFWiSi!5QZL+l7*CE?u!NW1T$<1rdLJ9y3u{_zvHaM?#Rm4 zFk}^1!ffcrB|XK3gsO-s=wr*sUe&^$yN|KxrA)uW00Gu60%pw_+DcUjW`oW<35OC8 zq2{j8SgC}W$?10pvFU83(SL$%C?Kctu3*cs0aa%q!fjn1%xD*Jrm!F3HGR9-C{b?- zHp(cL;ezXMpL@0-1v0DMWddSDNZ5h?q50cOZyVi#bU3&PWE=(hpVn|M4_KYG5h9LffKNRsfhr^=SYiKg?#r&HNMi2@cd4aYL9lw(5_IvQJ zcB*DD()hUSAD^PdA0y|QrVnqwgI@pUXZXjHq3lG2OU&7sPOxxU$Y3&ytj6Qb=2#cC z;{d-{k|xI*bu+Vy&N+}{i(+1me!M;nshY_*&ZQLTGG*xNw#{RpI`3^eGfHck+*38NRgiGahkFethtVY=czJs#)VVc{T65rhU#3Vf?X)8f0)X{w!J3J{z|Sq|%?)nA+zo?$>L9@o`Kc|*7sJo4UjIqu0Ir~S5k^vEH};6K?-dZ0h*m%-1L zf!VC%YbM1~sZOG5zu&Sh>R;(md*_)kGHP)<;OA44W?y53PI%{&@MEN}9TOiqu+1a3AGetBr$c)Ao3OX>iGxmA;^^_alwS818r4Pn&uYe^;z6dh z)68T|AN=hjNdGpF7n>y+RTAZc9&opTXf zqWfK_dUv=mW{p_vN>|(cIkd(+Jy}qnK{IW%X*3!l`^H~FbAHwof+vLZ0C2ZXN1$v7 zgN&R9c8IO`fkR{6U%ERq8FN<1DQYbAN0-pH7EfcA{A&nhT!Be>jj>J!bNRw4NF|}! z1c70_#fkk!VQ!q1h2ff@`yDyrI1`np>*e#D4-Z~*!T^8#o*$V~!8bWQaie?P@KGBb z8rXc!YDL!$3ZgZZ%;-%~0Kn<+d+{xJ$stQbtN8GWV?MCJvzPU|(E(1z;rFw{&6vy) z3*@y%7Tx8rH-p$boS>bLyod?OKRE8v`QSBvGfY6f}_{Zo1q85xoyOF16n~yHx2W ziydUoYLkJmzq|n&2S(O!ZmLdP1(o1Jsq88cX)x3V-BK5eF&0e_0G!5?U7&3KN0`mc zH&Lt)q8!d_VgzxyL^(@xrbp2y)Hmr^V48));RSfE=*Ly0uh9!$3dv-vMZr2URf@l5zdwLjGZB zugY>7_fd_vbV*Qv1?H~>Z%RD%nEeFSI$n$$Lrpc6g>i4+XdBB!%zM$Bhrz5Swzyg? z$~I~n@~-wTBY3-T&pr+|gC+OHDoR?I(eLWa{Z#Rsh>lc~%u0!&R|s0pA*w<7QZ}{i z*AFr~0F3y~f$MGh_HDL7J_1?SxKL}fWIk!$G}`^{)xh*dZ5kK>xGL9>V`WZZg_ z)^Vm)EQK`yfh5KiR(vb&aHvhich z_5o+{d~0+4BEBqYJXyXBIEb1UgVDs;a!N2$9WA>CbfrWryqT25)S4E4)QXBd*3jN} z?phkAt`1rKW?xoLzEm!*IfkH|P>BtECVr0l8-IGk_`UjE#IWkUGqvyS+dMrCnFl<7RCgSMX^qn|Ld_4iYRldO zY&cHhv)GDo8nKvKwAbfyLR%t?9gG?R7~PSD#4D-;?F&!kV59O}neYut5AGbKwy-(U zqyBi=&Mgj|VIo>$u!DHM`R7O?W8-idbePuxiJMH``6c_5L-chKd}=rGC5Gfrc{f!* zWFEBm?l@_b7kzY7%1RQQbG5V<4=ZlkZ%sF74Q|mKOc7Ak7dP2#quiGcZ0_J%7Q?j{ zv9{WFw;n5G-Mn%r#0R;{jLt{yy}9J6rQ(>X9pJ`7Xy?Zv z=lNit#qXaq?CnElK^zF~sG}U5oCpR0T>FH=ZX}Prju$);?;VOhFH8L3I><9P_A|C+ z{;>~dk%9rrq(snjsEm}oUz2FQ21MCG*e?g)?{!&|eg7PX@I+Q0!hL6C7ZVY|g2E>i zr!Ri2@OfEu$)d52+>+cpgh6Z;cLYCZ&EMR0i<^~4&wEu_bdo;y^6}+U2GIQgW$|Od z_jg{O=pU>0-H$P-EOlWyQy#W0r@@_uT}Lg+!d5NxMii7aT1=|qm6BRaWOf{Pws54v zTu=}LR!V(JzI07>QR;;px0+zq=(s+XH-0~rVbmGp8<)7G+Jf)UYs<$Dd>-K+4}CsD zS}KYLmkbRvjwBO3PB%2@j(vOpm)!JABH_E7X^f#V-bzifSaKtE)|QrczC1$sC<<*Y z$hY*3E10fYk`2W09gM_U<2>+r^+ro$Bqh-O7uSa)cfPE_<#^O) zF+5V;-8LaCLKdIh3UB@idQZL`0Vx8`OE#6*1<;8(zi&E7MWB1S%~HAm%axyIHN2vd zA(pJGm_PraB0Aat3~?obWBs?iSc*NhM!{-l_WNCx4@F7I?)5&oI|z{o@JKd1HZ}zf*#}JjK3$ z-;3V*WJZvUcKvSOBH4c7C{fl8oRw8-vfgKQjNiR|KhQ%k6hWNEke(k8w-Ro| z7Y3)FsY-?7%;VT64vRM)l0%&HI~BXkSAOV#F3Bf#|3QLZM%6C{paqLTb3MU-_)`{R zRdfVQ)uX90VCa3ja$8m;cdtxQ*(tNjIfVb%#TCJWeH?o4RY#LWpyZBJHR| z6G-!4W5O^Z8U}e5GfZ!_M{B``ve{r0Z#CXV0x@~X#Pc;}{{ClY_uw^=wWurj0RKnoFzeY` z;gS!PCLCo*c}-hLc?C&wv&>P1hH75=p#;D3{Q8UZ0ctX!b)_@Ur=WCMEuz>pTs$@s z#7bIutL9Pm2FDb~d+H}uBI#pu6R}T{nzpz9U0XLb9lu@=9bTY&PEyFwhHHtXFX~6C zrcg|qqTk(|MIM%KQ<@j=DOjt|V)+8K26wE_CBNnZTg+Z+s}AU|jp6CFoIptG1{J*# z7Ne~l;ba*=bSwAMQ|Vq#fW~+je4PXA91YFzBubNF?ovIOw-$C-8=Ehed{lGD0}(Id zRe4sh8L>&T%{>8o))he}eE;5_ zxoXk3wX?MyNl-xF!q1d$G?=wp^`@09(jU&X zOqZIBI#dN`2PJNdATR3ivtub|nO$dulSaP|e4)WXF1YAGN1pDQIbIjXFG!oC85Mt; zW$eteoL{y^5t4TMRwP$jNPjZFpGsWnGe=jMMqKtcZm9Y9PFZLi*1p@qoKKub^T@2+ zk$@*KYdQ?Z`}<%4ALwk*Yc{(WTf@#u;as(fvE^9{Gk)lWbJP*SjttWofV0s?AB({~l zZI1hZVWFT~W-T?nfMMcnCS4-#6H-MU7H$KxD;yaM46K4Kc@~Q>xzB+QnD_I`b_l3m zo9pRx46b!p?a^&zCDwygqqV3epjs(s0NQI6ARA1n!Yy-qduipxQ& zUAlqRpNjBS+y-ZheD(!R;F}&^V_}b_gqH%tVZ5%%ziO7k^w=es+wZtK^i*vmrWNLMs{oWu_CIov|s1raZiS)>38>pYu;i+-t zI_DiNe6aA4KTZ2P09qPj(0~K4nUq^0+f(2$g`229zkG4jLzRvJUWE0oF1XHL4t3UN zDH466G56sy9hTZoAJB!C3;@F;ONxEk5u6Mv%zdo}Rq`=* zw1n7MOhfNSV48TS989ArIcj`C%Gk8~93~u>)!Yt2b4ZriKj9x2d`H2HQNJ=I>hkDlcZn zqRj>!;oRMTIOu zx|Zfsu~v76T{z7AC(jxj^c@tnJHZtGPsq$DE!8kqvkDx5W?KUJPL+!Ffpwfa+|5z5 zKPCiOPqZZrAG;2%OH0T$W|`C@C*!Z`@Wkop{CTjB&Tk`+{XPnt`ND`Haz;xV`H^RS zyXYtw@WlqTvToi;=mq1<-|IQ(gcOpU%)b#_46|IuWL#4$oYLbqwuk6=Q@xZaJSKVF zZcHs~ZBl;&lF3=+nK; zF`4gSCeZXlwmC_t4I`#PUNQ*)Uv&oGxMALip|sxv^lyVV73tKI7)+QY5=tEMas{vTD-BaTJ^*Y6gq~PU;F5X!sxqiq$iFCo+Uv7m%1w((=e}Vf*=dtds|6 zbX}91!G?C*KG03eHoN}RZS9DJxa&8YwNCT8?JxMXyZqZr13NA|GB{+vG`08C{V(yy zf*Lw$+tYSU_+dI`3n{bMrPdDb`A=Mkg!O=k>1|*3MC8j~- zXL79J4E=U^H=iBLTeHE_OKzE&dws8RNynsSJ!d;`zK?P92U{f)xvD7VQVosrXZrL+ z6lMVdD1YgL;%(1cq{#bS6yXmp|DS@nax#AqqlZhtUQdh<^2vr5`EpAO

LGYq)sa(w9^3-f}NHy=GR4v%t2YZly3m1G@5y`xBh_HGrD%f z>;|Ty?9FiJAc&UVD(StT4I` zfVQwxhE9bXE6r2mKO8Ag7{L^jCyqQb0QqKDPE=RAgqn8q1O^>(z7h5kE(6va%QqRZ zkIOmp(})rLSS(2{=C12e&@!W2=Jel-^_R``0xHO^+t!(oXbcv5yhD4g*$t_F)_5Dl zSVCgesW%;DtYPCFs{G;GX_o?1J3;QQPPv)rWw;>} zJ&KwnUqwNXloNXlK_+pNDfI~hON#SokVJb&ilg8d7^NWo2ZQymCqQMnjfi>ePibjr z-Z@q!?RGN$Mj}Nk){X_vaj6?Mj$>ACR*z|6MsXy3VZ^PFn@yHkPo(>m(iWepn8SC@ z>D2;R4m+gDRZ=SIX!b+CP(qE=JDIUkn=D$aUu+Ihn9-+k1LS3PreQg0N5eWIG@x${nC3v^7caS>1!PKNAY9J z#}E}Q9w#SP>(GY7Hbj&z4$Li6o5taBO|4+F`yS9zq*LJ<38wy4I>HA9(&GYrk4dLajKGww))BWli6Ln1A^Lda@N~p+snkb9C z@OthI+<##vp8!HVQT4Wk(=@zQ{OvZ$EKWS73+JHb)eYLGD-cqi6^|vd$<+IHuc?Nq zW7JertT~3))4?J|28n$I@nAD0c1%9C&IVhEZX~mUsf{efyS(XNG%ch;!N~d7S(Ri7 zb&=BuON95aVA&kLn6&MVU|x}xPMp7xwWxNU1wS+F6#y}1@^wQZB*(&ecT?RnQcI}Y z2*z!^!D?gDUhc@;M^OpLs4mq>C&p{}OWVv<)S9KMars@0JQ{c_ScGsFo3BJ)Irg++ zAWwypJdTO-_{Uh8m(Z!3KL7K{ZZzKHj;{M8I$mV>k znTM?sa0);^=X^cglL`uC+^J)M7nEa$w=VwFULg~%DJllw+7dJAj3{qnP5i3@wr7%y zjXp?Wl2%Th=my&3u?Q$RV6N5tzKMSPTsc#J+-cDDp~qFB6bL2C8AS7Y3PKtVhdhl) zIaLqH5+OnWPWSt(lQCgkN8lczc-V%_iZ{>#1%Z$N*>lu#S;0MZ$T2Y8Kg!U;hAZj> z6S#%$DQ_`Ic%Zr@?}GgjRXg@qTj^17n`65oJ@Wj0u1X8&+UVd|Xs?J+i_^GZ94m6= zUc96~Q`OJvlKB_Lr15*Yw_PUPEr?f?H&00b^-W%26mD)(n(rGGNfK9~2h=C>p-7BZ zFd&*&Msdu{w~(eyFOglwCPH^Rb}O(N7LtS+nnEwDx*pGD?|&9Si~M43a+*L(b0$5A zv`T`(G3xO;I_sx;FwTP21ZlfDpz zOo?}Vlgf~fo{YWm@n_JyD*frOg{XsvBA~|Tn4V6hu>Gd>89-rblfVJUaGvj6X%NZ} z$tFF9sx=4_$*c~G`9iPLGh@=sV+O{D2-t*K@J7H=`V+oVt}8?04WwU3h1BgS!f%1P zFak-T#7`TtLcR=Yz>g0R!ZQrH!YiZOQN=_V-UyncN1Rc18?KY?#O`v#JK+pq0K$~H z3D@v9DZF42R)b9#BBX{^$DOMlJ!g)Gc za{o-1e%F6NvgKq9tC8pV+9S$;9*zNv{J*)n&dmf~anP1)4~N%~h#c(=B#3*KgzhCKhFdgDoWi2IDog{RVyzK|Y`rCUs3T~pJMmdZJy4?b z&s5G=zhf**(t7Y^oC_mcTsE-{^}wiaoUu&?kojLKs>SJPxjcP>{a5CbXCx92AcBE) zHtqP}LjZ{W>PH?Tu(E0X=%{PBMW@F_?#7b&#!^q`<-5$ur+-q6 z{dn=(^UZw6*3-XM_(=@<1_*i&XM4=0t5u!gm6 z{UlmNGPKgO_;e;q9|#esq~Sq`<}%d{+sRmhvsA{5i*91=tub>OZZ%)xUA#4q$dDyy z1`w4%?OPLg3JeZb#cqSMO?*Xn%|-FCcuH2i2fn_{IFusub6;NQdN|7TD1N?%E8*g? z$apAt@cEe!I%jB=*q$p_3=t_5R0ph%{qaq+QDg!c99Y!Xa!&oDZOeis_ot)gNXr{l zdY$|So2Qed2Y7KMNBrS^E169kG%h<+z{Z_p_;shB!uY)>yAVcK=&!bg`lVg)4T1|7 z0}7FpfydVH4F87K@c!nEG+WGKm{Ouo)Slpl;#qcEIQ0zdMfLA#;dBxYw;p;KoVv6| z3_D5&7rJdG12CnDSvZUW?$UC6^UVSW^|vw|o-_4bz)(w5(3AiVhpeT(|=f#x_}E?s#qHZF#xA6AF_ujl$G z-jHD%q(d2}v2PhXx&6YWps~m(^+RXl91Q#xRRJBhjKl$FG4bk);|ag;ieUZ&!Ii3$ z(iGz1+0m7#g5>ASldBbNZL=ZHh=tmmJt$!71; zIML2GhEz1pg@1rQN(M^_691wAGkJ@Pga_05WuQ6! zG5RkGY2^`@(H~pp7&Ga+Pwh3L!Njj!-rc;^bTIfo5hP@H##1X8xUZJckrx>id`bAd3QUx9GuomqBYZ!uN1-&o zvTxC?;p8vL67&fW8fw(YOqt>L@bdLrEF*3OgYe$4n4{ zEB40LiU#6-0@5jdN`0w}N0qi@c0~oT2FP z)LNk&a82my?jv(tQpiMi$TK_L@lub#lsM$R{Dk?Ya@%%%huZkct~tSWM714c!45k}-ZLVA-bVM`>|_ZBbW_m-7| z3U%xrAhi}n?T(2F{_n4EZ10inkIFl#y09?7$uwBoJgqY8vylwev)fDOn;>0R!aEnV zBz%j0Mqpx~EZU3q@%+oV7;}|vt7$~ou@faEIq{p?FY$XXg&6*K)b_LP=}gi9`Bij3 zN`zEo|B6*|-;>S`rNa^BKRDbDAk>X#MsR`EvL>6bqU@SaDDs z8>bu@3YdRaWs*Te@G-UHjU%F~kTHw5(0PVJ+pwh#ha2u;DB+UMo@A5UYIl#5rtBV- zGX_hIpw}3C@H*Us(Cc-d#-gNrG#w$(9+S=GxO>3SR`SE2fHZ2KrDc#_C^$jI>Y}#; zMwY=R6@+dWi~0RXw(c@3GZ&%~9K(q&ee0Zw;pwL`E_tZak-#8^_b)Dpyi73^he?xV zXJ08&wh5-M&}qy4f7!D&=E)puDD(Nmg1d_(j`4LvxM5x_huNg-pGG%9rYqO6mImyJ@}*3Y>^3OvcnTG%EV1) zq_Ap?Z!Iw__7#D=pOWnQN$gB!Mr0!9yx|g<4icJh{cFOu3B8}&RiYm+Mb;VEK``LK zL(NcpcTiGieOIssSjr?ob}^``nNf&UcJhXyncO9m{6gD$kqSD`S69(aF8dkWz5>!9 zBLe4Sib7Hs2x_L2Ls6Ish$MGVKrGt5+_2zCyP1byaCg3upo+-I}R4&$m)8 zQ7|jc1Z^VWggpuQj*cP;>Zo9LS!VSzrqmZczaf;u`d0J(f%Z9r%An@s!e>n9%y=n!IZ_tVGu{Jmsbp}Fk%HJIU?a+-~bjfLTuH|JExA8EROowzr zqW9{YyZhR0a4clRK>1I4Ncx&WER~{iE;F^$T7K%X@3PGOA%6#Z%p3TS^&M;Dnjw@i z^o!$9nhcsmcHcY4?4j9+ofL_CWsZ4Hcch(rjsGfGD(nsH>w}^ERqGnz%iGj0j{g}h z7wMkJ-2Z2~eS>2!i}0~B63i;>SyFJU2+>VCS^AxaDOx%g6-t0eM^P<3+*z`ztvOqrG3)&#$K?& z_Y0wbWID47@cU`E1A6A&!`aZk0ZE@z-h#l1NqX2#`$Uev2gepW`rf8*!=rD5&;Jb{ zl08rU>dPo=K%-1Ao1~G-@4ve~y5#9E8x;TE0k5d^TC(=Zc>mwjW^c=+U-<9}b0ku~}gj z3sbW>R2M6DR!g#NUP;nxo>)@7*=RP{U18SDop6b2&PHce^&h97@xx3t+VK+!keE#} z;(Uf&89as9k8{$nkLbuB!-d7TP`_VJpL^Xs8OKB~ri$YUbW8fch64}7|0EWoT(TRj{ z*GT<7Y<7DsrCi79ZsM)z#c(!nNOGySOCkY1fAuQOq12&iUVC!a`#O;dBLf=d?&4*B zI~LgAO7E0qxK(uRTM;IgJ}+z^gD+bi-6I!3x{r9`l~%8TRP%UE0V8E*Sz>Nl1NVG<<7(wDHZ+HcOkQm$O&k+vyx)y)x{Pz!U8hS$*m zByc0h6BUI*BOpuL==P+H|Hx%`>7!W+1H!l9vi&)`V zyn2o9{z=lc+VX*!Vh~SF=)L}Z40XeG>LF6cP^b+R$NxSeUqbK^Q*UTalKzP8X%{9@RSCXm_NhF>{=S2 zi}ezam_^P`S!!-cyEW9y7DBbK93roz@Raccy*v}?mKXScU9E_4g;hBU7}zSofAFda zKYEe?{{I54 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 68e8816d71..2b189974c2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionSha256Sum=5b9c5eb3f9fc2c94abaea57d90bd78747ca117ddbbf96c859d3741181a12bf2a +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index b740cf1339..f5feea6d6b 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 7101f8e467..9b42019c79 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## From e9ad39a0bf05f0a4206a74f9838bc3080c664cc9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:37:30 +0200 Subject: [PATCH 133/186] Update lifecycle to v2.8.0 (#2848) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martin Espinosa Co-authored-by: Benoit Marty --- 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 e85170cde7..805c6459e6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ core = "1.13.1" datastore = "1.0.0" constraintlayout = "2.1.4" constraintlayout_compose = "1.0.1" -lifecycle = "2.7.0" +lifecycle = "2.8.0" activity = "1.9.1" media3 = "1.4.0" camera = "1.3.4" From 534e3a85853560ce55161bc0c462f0f7a05c9c68 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:03:01 +0000 Subject: [PATCH 134/186] Update lifecycle to v2.8.4 (#3315) 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 805c6459e6..a1a981cfe6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ core = "1.13.1" datastore = "1.0.0" constraintlayout = "2.1.4" constraintlayout_compose = "1.0.1" -lifecycle = "2.8.0" +lifecycle = "2.8.4" activity = "1.9.1" media3 = "1.4.0" camera = "1.3.4" From f2b38e50e36152c9c78a2c0c0995edc5212bab6e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 20 Aug 2024 17:11:30 +0200 Subject: [PATCH 135/186] Add test on function name which may start or end with spaces and fix existing issues. --- .../roomlist/impl/RoomListPresenterTest.kt | 2 +- .../mediaviewer/MediaViewerPresenterTest.kt | 2 +- .../push/impl/push/DefaultPushHandlerTest.kt | 2 +- .../tests/konsist/KonsistMethodNameTest.kt | 32 +++++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistMethodNameTest.kt diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt index 4bf4510d2f..a381dc414d 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt @@ -495,7 +495,7 @@ class RoomListPresenterTest { } @Test - fun `present - when room service returns no room, then contentState is Empty `() = runTest { + fun `present - when room service returns no room, then contentState is Empty`() = runTest { val scope = CoroutineScope(coroutineContext + SupervisorJob()) val roomListService = FakeRoomListService() roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(0)) diff --git a/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/MediaViewerPresenterTest.kt b/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/MediaViewerPresenterTest.kt index 67d8f7c3a1..23abdce74c 100644 --- a/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/MediaViewerPresenterTest.kt +++ b/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/MediaViewerPresenterTest.kt @@ -70,7 +70,7 @@ class MediaViewerPresenterTest { } @Test - fun `present - check all actions `() = runTest { + fun `present - check all actions`() = runTest { val matrixMediaLoader = FakeMatrixMediaLoader() val mediaActions = FakeLocalMediaActions() val snackbarDispatcher = SnackbarDispatcher() 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 4953e4d7b4..160f9f5135 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 @@ -306,7 +306,7 @@ class DefaultPushHandlerTest { } @Test - fun `when diagnostic PushData is received, the diagnostic push handler is informed `() = + fun `when diagnostic PushData is received, the diagnostic push handler is informed`() = runTest { val aPushData = PushData( eventId = DefaultTestPush.TEST_EVENT_ID, diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistMethodNameTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistMethodNameTest.kt new file mode 100644 index 0000000000..2d3a91c093 --- /dev/null +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistMethodNameTest.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.tests.konsist + +import com.lemonappdev.konsist.api.Konsist +import com.lemonappdev.konsist.api.verify.assertTrue +import org.junit.Test + +class KonsistMethodNameTest { + @Test + fun `Ensure that method name does not start or end with spaces`() { + Konsist.scopeFromProject() + .functions() + .assertTrue { + it.name.trim() == it.name + } + } +} From 0686745fd4b2d0e5e3b32d28d6d54a355f54beff Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 20 Aug 2024 21:04:20 +0200 Subject: [PATCH 136/186] Fix reset identity with password stuck in loading state. (#3317) Make sure `resetIdentityFlowManager.whenResetIsDone` is registered *after* the previous reset attempt is cancelled, otherwise the current one will be cancelled instead. --- .../impl/reset/ResetIdentityFlowNode.kt | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt index 50dcc2dd12..9bd8aeff03 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt @@ -87,20 +87,22 @@ class ResetIdentityFlowNode @AssistedInject constructor( override fun onBuilt() { super.onBuilt() - resetIdentityFlowManager.whenResetIsDone { - plugins().forEach { it.onDone() } - } - lifecycle.addObserver(object : DefaultLifecycleObserver { override fun onStart(owner: LifecycleOwner) { // If the custom tab was opened, we need to cancel the reset job // when we come back to the node if the reset wasn't successful - cancelResetJob() + coroutineScope.launch { + cancelResetJob() + + resetIdentityFlowManager.whenResetIsDone { + plugins().forEach { it.onDone() } + } + } } override fun onDestroy(owner: LifecycleOwner) { // Make sure we cancel the reset job when the node is destroyed, just in case - cancelResetJob() + coroutineScope.launch { cancelResetJob() } } }) } @@ -154,10 +156,10 @@ class ResetIdentityFlowNode @AssistedInject constructor( } } - private fun cancelResetJob() { + private suspend fun cancelResetJob() { resetJob?.cancel() resetJob = null - coroutineScope.launch { resetIdentityFlowManager.cancel() } + resetIdentityFlowManager.cancel() } @Composable @@ -171,7 +173,7 @@ class ResetIdentityFlowNode @AssistedInject constructor( if (startResetState.isLoading()) { ProgressDialog( properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = true), - onDismissRequest = { cancelResetJob() } + onDismissRequest = { coroutineScope.launch { cancelResetJob() } } ) } From 1b1062be243dcc497d2f004a2835c8d9f2de0240 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2024 08:48:22 +0000 Subject: [PATCH 137/186] Update dagger to v2.52 (#3270) 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 a1a981cfe6..9efb6341b2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -48,7 +48,7 @@ wysiwyg = "2.37.8" telephoto = "0.12.1" # DI -dagger = "2.51.1" +dagger = "2.52" anvil = "2.4.9" # Auto service From 57d927e9aa5d45d04bca73da000d95ab010da615 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 14:09:29 +0200 Subject: [PATCH 138/186] Suggestion for room alias. Rename `Mention` to `IntentionalMention` for clarity Remove dead code, there is no intentional mention for Room or RoomAlias. Rename `IntentionalMention.AtRoom` to `IntentionalMention.Room` to match Rust naming --- .../features/messages/impl/MessagesView.kt | 12 +-- .../mentions/MentionSuggestionsProcessor.kt | 18 +++- ...PickerView.kt => SuggestionsPickerView.kt} | 91 ++++++++++++------- .../messagecomposer/MessageComposerEvents.kt | 4 +- .../MessageComposerPresenter.kt | 59 +++++++----- .../messagecomposer/MessageComposerState.kt | 4 +- .../MessageComposerStateProvider.kt | 6 +- .../RoomAliasSuggestionsDataSource.kt | 58 ++++++++++++ .../messages/impl/MessagesPresenterTest.kt | 4 +- .../FakeRoomAliasSuggestionsDataSource.kt | 34 +++++++ .../MessageComposerPresenterTest.kt | 61 ++++++------- .../TestRichTextEditorStateFactory.kt | 3 +- .../impl/timeline/TimelineControllerTest.kt | 6 +- .../features/share/impl/SharePresenter.kt | 2 +- .../matrix/api/permalink/PermalinkBuilder.kt | 3 +- .../{Mention.kt => IntentionalMention.kt} | 9 +- .../libraries/matrix/api/room/MatrixRoom.kt | 4 +- .../libraries/matrix/api/timeline/Timeline.kt | 17 +++- .../impl/permalink/DefaultPermalinkBuilder.kt | 4 +- .../libraries/matrix/impl/room/Mention.kt | 10 +- .../matrix/impl/room/RustMatrixRoom.kt | 15 ++- .../matrix/impl/timeline/RustTimeline.kt | 18 ++-- .../matrix/impl/util/MessageEventContent.kt | 6 +- .../test/permalink/FakePermalinkBuilder.kt | 5 +- .../matrix/test/room/FakeMatrixRoom.kt | 14 +-- .../matrix/test/timeline/FakeTimeline.kt | 20 ++-- .../NotificationBroadcastReceiverHandler.kt | 4 +- .../components/markdown/MarkdownTextInput.kt | 8 +- ...ionSuggestion.kt => ResolvedSuggestion.kt} | 9 +- .../model/MarkdownTextEditorState.kt | 52 +++++++---- .../libraries/textcomposer/model/Message.kt | 4 +- .../markdown/MarkdownTextInputTest.kt | 8 +- ... => IntentionalMentionSpanProviderTest.kt} | 2 +- .../impl/model/MarkdownTextEditorStateTest.kt | 47 ++++++---- 34 files changed, 399 insertions(+), 222 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/{MentionSuggestionsPickerView.kt => SuggestionsPickerView.kt} (62%) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/RoomAliasSuggestionsDataSource.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/FakeRoomAliasSuggestionsDataSource.kt rename features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/{textcomposer => messagecomposer}/MessageComposerPresenterTest.kt (96%) rename features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/{textcomposer => messagecomposer}/TestRichTextEditorStateFactory.kt (86%) rename libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/{Mention.kt => IntentionalMention.kt} (71%) rename libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/{ResolvedMentionSuggestion.kt => ResolvedSuggestion.kt} (67%) rename libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/{MentionSpanProviderTest.kt => IntentionalMentionSpanProviderTest.kt} (98%) 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 df6aa26778..7d883894b0 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 @@ -66,7 +66,7 @@ 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.attachments.Attachment -import io.element.android.features.messages.impl.mentions.MentionSuggestionsPickerView +import io.element.android.features.messages.impl.mentions.SuggestionsPickerView import io.element.android.features.messages.impl.messagecomposer.AttachmentsBottomSheet import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents @@ -377,7 +377,7 @@ private fun MessagesViewContent( @Composable {} }, sheetSwipeEnabled = state.composerState.showTextFormatting, - sheetShape = if (state.composerState.showTextFormatting || state.composerState.memberSuggestions.isNotEmpty()) { + sheetShape = if (state.composerState.showTextFormatting || state.composerState.suggestions.isNotEmpty()) { MaterialTheme.shapes.large } else { RectangleShape @@ -427,7 +427,7 @@ private fun MessagesViewContent( }, sheetContentKey = sheetResizeContentKey.intValue, sheetTonalElevation = 0.dp, - sheetShadowElevation = if (state.composerState.memberSuggestions.isNotEmpty()) 16.dp else 0.dp, + sheetShadowElevation = if (state.composerState.suggestions.isNotEmpty()) 16.dp else 0.dp, ) } } @@ -439,7 +439,7 @@ private fun MessagesViewComposerBottomSheetContents( ) { if (state.userEventPermissions.canSendMessage) { Column(modifier = Modifier.fillMaxWidth()) { - MentionSuggestionsPickerView( + SuggestionsPickerView( modifier = Modifier .heightIn(max = 230.dp) // Consume all scrolling, preventing the bottom sheet from being dragged when interacting with the list of suggestions @@ -451,9 +451,9 @@ private fun MessagesViewComposerBottomSheetContents( roomId = state.roomId, roomName = state.roomName.dataOrNull(), roomAvatarData = state.roomAvatar.dataOrNull(), - memberSuggestions = state.composerState.memberSuggestions, + suggestions = state.composerState.suggestions, onSelectSuggestion = { - state.composerState.eventSink(MessageComposerEvents.InsertMention(it)) + state.composerState.eventSink(MessageComposerEvents.InsertSuggestion(it)) } ) MessageComposerView( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt index f0e89c1148..4467481cb5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt @@ -16,13 +16,14 @@ package io.element.android.features.messages.impl.mentions +import io.element.android.features.messages.impl.messagecomposer.RoomAliasSuggestion import io.element.android.libraries.core.data.filterUpTo import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState 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.roomMembers -import io.element.android.libraries.textcomposer.mentions.ResolvedMentionSuggestion +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.Suggestion import io.element.android.libraries.textcomposer.model.SuggestionType @@ -37,6 +38,7 @@ object MentionSuggestionsProcessor { * Process the mention suggestions. * @param suggestion The current suggestion input * @param roomMembersState The room members state, it contains the current users in the room + * @param roomAliasSuggestions The available room alias suggestions * @param currentUserId The current user id * @param canSendRoomMention Should return true if the current user can send room mentions * @return The list of mentions to display @@ -44,9 +46,10 @@ object MentionSuggestionsProcessor { suspend fun process( suggestion: Suggestion?, roomMembersState: MatrixRoomMembersState, + roomAliasSuggestions: List, currentUserId: UserId, canSendRoomMention: suspend () -> Boolean, - ): List { + ): List { val members = roomMembersState.roomMembers() return when { members.isNullOrEmpty() || suggestion == null -> { @@ -65,6 +68,11 @@ object MentionSuggestionsProcessor { ) matchingMembers } + SuggestionType.Room -> { + roomAliasSuggestions + .filter { it.roomAlias.value.contains(suggestion.text, ignoreCase = true) } + .map { ResolvedSuggestion.Alias(it.roomAlias, it.roomSummary) } + } else -> { // Clear suggestions emptyList() @@ -79,7 +87,7 @@ object MentionSuggestionsProcessor { roomMembers: List?, currentUserId: UserId, canSendRoomMention: Boolean, - ): List { + ): List { return if (roomMembers.isNullOrEmpty()) { emptyList() } else { @@ -97,10 +105,10 @@ object MentionSuggestionsProcessor { .filterUpTo(MAX_BATCH_ITEMS) { member -> isJoinedMemberAndNotSelf(member) && memberMatchesQuery(member, query) } - .map(ResolvedMentionSuggestion::Member) + .map(ResolvedSuggestion::Member) if ("room".contains(query) && canSendRoomMention) { - listOf(ResolvedMentionSuggestion.AtRoom) + matchingMembers + listOf(ResolvedSuggestion.AtRoom) + matchingMembers } else { matchingMembers } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsPickerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsPickerView.kt similarity index 62% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsPickerView.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsPickerView.kt index 48c626680e..f9adc75c20 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsPickerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsPickerView.kt @@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -39,38 +40,41 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipState -import io.element.android.libraries.textcomposer.mentions.ResolvedMentionSuggestion +import io.element.android.libraries.matrix.ui.components.aRoomSummaryDetails +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @Composable -fun MentionSuggestionsPickerView( +fun SuggestionsPickerView( roomId: RoomId, roomName: String?, roomAvatarData: AvatarData?, - memberSuggestions: ImmutableList, - onSelectSuggestion: (ResolvedMentionSuggestion) -> Unit, + suggestions: ImmutableList, + onSelectSuggestion: (ResolvedSuggestion) -> Unit, modifier: Modifier = Modifier, ) { LazyColumn( modifier = modifier.fillMaxWidth(), ) { items( - memberSuggestions, + suggestions, key = { suggestion -> when (suggestion) { - is ResolvedMentionSuggestion.AtRoom -> "@room" - is ResolvedMentionSuggestion.Member -> suggestion.roomMember.userId.value + is ResolvedSuggestion.AtRoom -> "@room" + is ResolvedSuggestion.Member -> suggestion.roomMember.userId.value + is ResolvedSuggestion.Alias -> suggestion.roomAlias.value } } ) { Column(modifier = Modifier.fillParentMaxWidth()) { - RoomMemberSuggestionItemView( - memberSuggestion = it, + SuggestionItemView( + suggestion = it, roomId = roomId.value, roomName = roomName, roomAvatar = roomAvatarData, @@ -84,33 +88,44 @@ fun MentionSuggestionsPickerView( } @Composable -private fun RoomMemberSuggestionItemView( - memberSuggestion: ResolvedMentionSuggestion, +private fun SuggestionItemView( + suggestion: ResolvedSuggestion, roomId: String, roomName: String?, roomAvatar: AvatarData?, - onSelectSuggestion: (ResolvedMentionSuggestion) -> Unit, + onSelectSuggestion: (ResolvedSuggestion) -> Unit, modifier: Modifier = Modifier, ) { - Row(modifier = modifier.clickable { onSelectSuggestion(memberSuggestion) }, horizontalArrangement = Arrangement.spacedBy(16.dp)) { - val avatarData = when (memberSuggestion) { - is ResolvedMentionSuggestion.AtRoom -> roomAvatar?.copy(size = AvatarSize.Suggestion) - ?: AvatarData(roomId, roomName, null, AvatarSize.Suggestion) - is ResolvedMentionSuggestion.Member -> AvatarData( - id = memberSuggestion.roomMember.userId.value, - name = memberSuggestion.roomMember.displayName, - url = memberSuggestion.roomMember.avatarUrl, - size = AvatarSize.Suggestion, + Row( + modifier = modifier.clickable { onSelectSuggestion(suggestion) }, + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + val avatarSize = AvatarSize.Suggestion + val avatarData = when (suggestion) { + is ResolvedSuggestion.AtRoom -> roomAvatar?.copy(size = avatarSize) ?: AvatarData(roomId, roomName, null, avatarSize) + is ResolvedSuggestion.Member -> AvatarData( + suggestion.roomMember.userId.value, + suggestion.roomMember.displayName, + suggestion.roomMember.avatarUrl, + avatarSize, + ) + is ResolvedSuggestion.Alias -> AvatarData( + suggestion.roomSummary.roomId.value, + suggestion.roomSummary.name, + suggestion.roomSummary.avatarUrl, + avatarSize, ) } - val title = when (memberSuggestion) { - is ResolvedMentionSuggestion.AtRoom -> stringResource(R.string.screen_room_mentions_at_room_title) - is ResolvedMentionSuggestion.Member -> memberSuggestion.roomMember.displayName + val title = when (suggestion) { + is ResolvedSuggestion.AtRoom -> stringResource(R.string.screen_room_mentions_at_room_title) + is ResolvedSuggestion.Member -> suggestion.roomMember.displayName + is ResolvedSuggestion.Alias -> suggestion.roomSummary.name } - val subtitle = when (memberSuggestion) { - is ResolvedMentionSuggestion.AtRoom -> "@room" - is ResolvedMentionSuggestion.Member -> memberSuggestion.roomMember.userId.value + val subtitle = when (suggestion) { + is ResolvedSuggestion.AtRoom -> "@room" + is ResolvedSuggestion.Member -> suggestion.roomMember.userId.value + is ResolvedSuggestion.Alias -> suggestion.roomAlias.value } Avatar(avatarData = avatarData, modifier = Modifier.padding(start = 16.dp, top = 12.dp, bottom = 12.dp)) @@ -142,7 +157,7 @@ private fun RoomMemberSuggestionItemView( @PreviewsDayNight @Composable -internal fun MentionSuggestionsPickerViewPreview() { +internal fun SuggestionsPickerViewPreview() { ElementPreview { val roomMember = RoomMember( userId = UserId("@alice:server.org"), @@ -155,14 +170,24 @@ internal fun MentionSuggestionsPickerViewPreview() { isIgnored = false, role = RoomMember.Role.USER, ) - MentionSuggestionsPickerView( + val anAlias = remember { RoomAlias("#room:domain.org") } + val roomSummaryDetails = remember { + aRoomSummaryDetails( + name = "My room", + ) + } + SuggestionsPickerView( roomId = RoomId("!room:matrix.org"), roomName = "Room", roomAvatarData = null, - memberSuggestions = persistentListOf( - ResolvedMentionSuggestion.AtRoom, - ResolvedMentionSuggestion.Member(roomMember), - ResolvedMentionSuggestion.Member(roomMember.copy(userId = UserId("@bob:server.org"), displayName = "Bob")), + suggestions = persistentListOf( + ResolvedSuggestion.AtRoom, + ResolvedSuggestion.Member(roomMember), + ResolvedSuggestion.Member(roomMember.copy(userId = UserId("@bob:server.org"), displayName = "Bob")), + ResolvedSuggestion.Alias( + anAlias, + roomSummaryDetails, + ) ), onSelectSuggestion = {} ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt index 1f6ae7c7f4..d5f3429450 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt @@ -18,7 +18,7 @@ package io.element.android.features.messages.impl.messagecomposer import android.net.Uri import androidx.compose.runtime.Immutable -import io.element.android.libraries.textcomposer.mentions.ResolvedMentionSuggestion +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.Suggestion @@ -44,6 +44,6 @@ sealed interface MessageComposerEvents { data class Error(val error: Throwable) : MessageComposerEvents data class TypingNotice(val isTyping: Boolean) : MessageComposerEvents data class SuggestionReceived(val suggestion: Suggestion?) : MessageComposerEvents - data class InsertMention(val mention: ResolvedMentionSuggestion) : MessageComposerEvents + data class InsertSuggestion(val resolvedSuggestion: ResolvedSuggestion) : MessageComposerEvents data object SaveDraft : MessageComposerEvents } 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 d0e50d114c..114a0fdb2a 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,8 +55,8 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkParser +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.MatrixRoom -import io.element.android.libraries.matrix.api.room.Mention 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.isDm @@ -72,7 +72,7 @@ import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.textcomposer.mentions.LocalMentionSpanTheme import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider -import io.element.android.libraries.textcomposer.mentions.ResolvedMentionSuggestion +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.MarkdownTextEditorState import io.element.android.libraries.textcomposer.model.Message import io.element.android.libraries.textcomposer.model.MessageComposerMode @@ -117,6 +117,7 @@ class MessageComposerPresenter @Inject constructor( private val analyticsService: AnalyticsService, private val messageComposerContext: DefaultMessageComposerContext, private val richTextEditorStateFactory: RichTextEditorStateFactory, + private val roomAliasSuggestionsDataSource: RoomAliasSuggestionsDataSource, private val permalinkParser: PermalinkParser, private val permalinkBuilder: PermalinkBuilder, permissionsPresenterFactory: PermissionsPresenter.Factory, @@ -189,6 +190,8 @@ class MessageComposerPresenter @Inject constructor( val sendTypingNotifications by sessionPreferencesStore.isSendTypingNotificationsEnabled().collectAsState(initial = true) + val roomAliasSuggestions by roomAliasSuggestionsDataSource.getAllRoomAliasSuggestions().collectAsState(initial = emptyList()) + LaunchedEffect(attachmentsState.value) { when (val attachmentStateValue = attachmentsState.value) { is AttachmentsState.Sending.Processing -> { @@ -212,7 +215,7 @@ class MessageComposerPresenter @Inject constructor( } } - val memberSuggestions = remember { mutableStateListOf() } + val suggestions = remember { mutableStateListOf() } LaunchedEffect(isMentionsEnabled) { if (!isMentionsEnabled) return@LaunchedEffect val currentUserId = room.sessionId @@ -228,15 +231,16 @@ class MessageComposerPresenter @Inject constructor( val mentionCompletionTrigger = suggestionSearchTrigger.debounce(0.3.seconds).filter { !it?.text.isNullOrEmpty() } merge(mentionStartTrigger, mentionCompletionTrigger) .combine(room.membersStateFlow) { suggestion, roomMembersState -> - memberSuggestions.clear() + suggestions.clear() val result = MentionSuggestionsProcessor.process( suggestion = suggestion, roomMembersState = roomMembersState, + roomAliasSuggestions = roomAliasSuggestions, currentUserId = currentUserId, canSendRoomMention = ::canSendRoomMention, ) if (result.isNotEmpty()) { - memberSuggestions.addAll(result) + suggestions.addAll(result) } } .collect() @@ -362,22 +366,27 @@ class MessageComposerPresenter @Inject constructor( is MessageComposerEvents.SuggestionReceived -> { suggestionSearchTrigger.value = event.suggestion } - is MessageComposerEvents.InsertMention -> { + is MessageComposerEvents.InsertSuggestion -> { localCoroutineScope.launch { if (showTextFormatting) { - when (val mention = event.mention) { - is ResolvedMentionSuggestion.AtRoom -> { + when (val suggestion = event.resolvedSuggestion) { + is ResolvedSuggestion.AtRoom -> { richTextEditorState.insertAtRoomMentionAtSuggestion() } - is ResolvedMentionSuggestion.Member -> { - val text = mention.roomMember.userId.value - val link = permalinkBuilder.permalinkForUser(mention.roomMember.userId).getOrNull() ?: return@launch + is ResolvedSuggestion.Member -> { + val text = suggestion.roomMember.userId.value + val link = permalinkBuilder.permalinkForUser(suggestion.roomMember.userId).getOrNull() ?: return@launch + richTextEditorState.insertMentionAtSuggestion(text = text, link = link) + } + is ResolvedSuggestion.Alias -> { + val text = suggestion.roomAlias.value + val link = permalinkBuilder.permalinkForRoomAlias(suggestion.roomAlias).getOrNull() ?: return@launch richTextEditorState.insertMentionAtSuggestion(text = text, link = link) } } - } else if (markdownTextEditorState.currentMentionSuggestion != null) { - markdownTextEditorState.insertMention( - mention = event.mention, + } else if (markdownTextEditorState.currentSuggestion != null) { + markdownTextEditorState.insertSuggestion( + resolvedSuggestion = event.resolvedSuggestion, mentionSpanProvider = mentionSpanProvider, permalinkBuilder = permalinkBuilder, ) @@ -417,7 +426,7 @@ class MessageComposerPresenter @Inject constructor( canShareLocation = canShareLocation.value, canCreatePoll = canCreatePoll.value, attachmentsState = attachmentsState.value, - memberSuggestions = memberSuggestions.toPersistentList(), + suggestions = suggestions.toPersistentList(), resolveMentionDisplay = resolveMentionDisplay, eventSink = { handleEvents(it) }, ) @@ -432,17 +441,21 @@ class MessageComposerPresenter @Inject constructor( // Reset composer right away resetComposer(markdownTextEditorState, richTextEditorState, fromEdit = capturedMode is MessageComposerMode.Edit) when (capturedMode) { - is MessageComposerMode.Normal -> room.sendMessage(body = message.markdown, htmlBody = message.html, mentions = message.mentions) + is MessageComposerMode.Normal -> room.sendMessage( + body = message.markdown, + htmlBody = message.html, + intentionalMentions = message.intentionalMentions + ) is MessageComposerMode.Edit -> { val eventId = capturedMode.eventId val transactionId = capturedMode.transactionId timelineController.invokeOnCurrentTimeline { // First try to edit the message in the current timeline - editMessage(eventId, transactionId, message.markdown, message.html, message.mentions) + editMessage(eventId, transactionId, message.markdown, message.html, message.intentionalMentions) .onFailure { cause -> if (cause is TimelineException.EventNotFound && eventId != null) { // if the event is not found in the timeline, try to edit the message directly - room.editMessage(eventId, message.markdown, message.html, message.mentions) + room.editMessage(eventId, message.markdown, message.html, message.intentionalMentions) } } } @@ -450,7 +463,7 @@ class MessageComposerPresenter @Inject constructor( is MessageComposerMode.Reply -> { timelineController.invokeOnCurrentTimeline { - replyMessage(capturedMode.eventId, message.markdown, message.html, message.mentions) + replyMessage(capturedMode.eventId, message.markdown, message.html, message.intentionalMentions) } } } @@ -623,15 +636,15 @@ class MessageComposerPresenter @Inject constructor( ?.let { state -> buildList { if (state.hasAtRoomMention) { - add(Mention.AtRoom) + add(IntentionalMention.Room) } for (userId in state.userIds) { - add(Mention.User(UserId(userId))) + add(IntentionalMention.User(UserId(userId))) } } } .orEmpty() - Message(html = html, markdown = markdown, mentions = mentions) + Message(html = html, markdown = markdown, intentionalMentions = mentions) } else { val markdown = markdownTextEditorState.getMessageMarkdown(permalinkBuilder) val mentions = if (withMentions) { @@ -639,7 +652,7 @@ class MessageComposerPresenter @Inject constructor( } else { emptyList() } - Message(html = null, markdown = markdown, mentions = mentions) + Message(html = null, markdown = markdown, intentionalMentions = mentions) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt index 332a9e75f8..3698cdedbc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt @@ -19,7 +19,7 @@ package io.element.android.features.messages.impl.messagecomposer import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable import io.element.android.features.messages.impl.attachments.Attachment -import io.element.android.libraries.textcomposer.mentions.ResolvedMentionSuggestion +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.TextEditorState import io.element.android.wysiwyg.display.TextDisplay @@ -35,7 +35,7 @@ data class MessageComposerState( val canShareLocation: Boolean, val canCreatePoll: Boolean, val attachmentsState: AttachmentsState, - val memberSuggestions: ImmutableList, + val suggestions: ImmutableList, val resolveMentionDisplay: (String, String) -> TextDisplay, val eventSink: (MessageComposerEvents) -> Unit, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt index 824f87bb8e..b30074bb78 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt @@ -18,7 +18,7 @@ package io.element.android.features.messages.impl.messagecomposer import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.textcomposer.aRichTextEditorState -import io.element.android.libraries.textcomposer.mentions.ResolvedMentionSuggestion +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.TextEditorState import io.element.android.wysiwyg.display.TextDisplay @@ -41,7 +41,7 @@ fun aMessageComposerState( canShareLocation: Boolean = true, canCreatePoll: Boolean = true, attachmentsState: AttachmentsState = AttachmentsState.None, - memberSuggestions: ImmutableList = persistentListOf(), + suggestions: ImmutableList = persistentListOf(), ) = MessageComposerState( textEditorState = textEditorState, isFullScreen = isFullScreen, @@ -51,7 +51,7 @@ fun aMessageComposerState( canShareLocation = canShareLocation, canCreatePoll = canCreatePoll, attachmentsState = attachmentsState, - memberSuggestions = memberSuggestions, + suggestions = suggestions, resolveMentionDisplay = { _, _ -> TextDisplay.Plain }, eventSink = {}, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/RoomAliasSuggestionsDataSource.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/RoomAliasSuggestionsDataSource.kt new file mode 100644 index 0000000000..f905c29697 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/RoomAliasSuggestionsDataSource.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.messagecomposer + +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.RoomAlias +import io.element.android.libraries.matrix.api.roomlist.RoomListService +import io.element.android.libraries.matrix.api.roomlist.RoomSummary +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import javax.inject.Inject + +data class RoomAliasSuggestion( + val roomAlias: RoomAlias, + val roomSummary: RoomSummary, +) + +interface RoomAliasSuggestionsDataSource { + fun getAllRoomAliasSuggestions(): Flow> +} + +@ContributesBinding(SessionScope::class) +class DefaultRoomAliasSuggestionsDataSource @Inject constructor( + private val roomListService: RoomListService, +) : RoomAliasSuggestionsDataSource { + override fun getAllRoomAliasSuggestions(): Flow> { + return roomListService + .allRooms + .filteredSummaries + .map { roomSummaries -> + roomSummaries + .mapNotNull { roomSummary -> + roomSummary.canonicalAlias?.let { roomAlias -> + RoomAliasSuggestion( + roomAlias = roomAlias, + roomSummary = roomSummary, + ) + } + } + } + } +} + 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 a6c123971b..9bc223c341 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 @@ -29,9 +29,10 @@ import io.element.android.features.messages.impl.draft.FakeComposerDraftService import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactory import io.element.android.features.messages.impl.messagecomposer.DefaultMessageComposerContext +import io.element.android.features.messages.impl.messagecomposer.FakeRoomAliasSuggestionsDataSource import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter +import io.element.android.features.messages.impl.messagecomposer.TestRichTextEditorStateFactory import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState -import io.element.android.features.messages.impl.textcomposer.TestRichTextEditorStateFactory import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.timeline.TimelineItemIndexer import io.element.android.features.messages.impl.timeline.TimelinePresenter @@ -1008,6 +1009,7 @@ class MessagesPresenterTest { analyticsService = analyticsService, messageComposerContext = DefaultMessageComposerContext(), richTextEditorStateFactory = TestRichTextEditorStateFactory(), + roomAliasSuggestionsDataSource = FakeRoomAliasSuggestionsDataSource(), permissionsPresenterFactory = permissionsPresenterFactory, permalinkParser = FakePermalinkParser(), permalinkBuilder = FakePermalinkBuilder(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/FakeRoomAliasSuggestionsDataSource.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/FakeRoomAliasSuggestionsDataSource.kt new file mode 100644 index 0000000000..b7ee6f27ca --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/FakeRoomAliasSuggestionsDataSource.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.messagecomposer + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow + +class FakeRoomAliasSuggestionsDataSource( + initialData: List = emptyList() +) : RoomAliasSuggestionsDataSource { + private val roomAliasSuggestions = MutableStateFlow(initialData) + + override fun getAllRoomAliasSuggestions(): Flow> { + return roomAliasSuggestions + } + + fun emitRoomAliasSuggestions(newData: List) { + roomAliasSuggestions.value = newData + } +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt similarity index 96% rename from features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt rename to features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt index 924616de7a..e38f7e79c4 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt @@ -16,7 +16,7 @@ @file:OptIn(ExperimentalCoroutinesApi::class) -package io.element.android.features.messages.impl.textcomposer +package io.element.android.features.messages.impl.messagecomposer import android.net.Uri import androidx.compose.runtime.remember @@ -29,11 +29,6 @@ import im.vector.app.features.analytics.plan.Composer import im.vector.app.features.analytics.plan.Interaction import io.element.android.features.messages.impl.draft.ComposerDraftService import io.element.android.features.messages.impl.draft.FakeComposerDraftService -import io.element.android.features.messages.impl.messagecomposer.AttachmentsState -import io.element.android.features.messages.impl.messagecomposer.DefaultMessageComposerContext -import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents -import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter -import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper import io.element.android.features.messages.impl.utils.TextPillificationHelper @@ -52,7 +47,7 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType @@ -90,7 +85,7 @@ import io.element.android.libraries.permissions.test.FakePermissionsPresenterFac import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider -import io.element.android.libraries.textcomposer.mentions.ResolvedMentionSuggestion +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.Suggestion import io.element.android.libraries.textcomposer.model.SuggestionType @@ -368,7 +363,7 @@ class MessageComposerPresenterTest { @Test fun `present - edit sent message`() = runTest { - val editMessageLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String, _: String?, _: List -> + val editMessageLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String, _: String?, _: List -> Result.success(Unit) } val timeline = FakeTimeline().apply { @@ -420,13 +415,13 @@ class MessageComposerPresenterTest { @Test fun `present - edit sent message event not found`() = runTest { - val timelineEditMessageLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String, _: String?, _: List -> + val timelineEditMessageLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String, _: String?, _: List -> Result.failure(TimelineException.EventNotFound) } val timeline = FakeTimeline().apply { this.editMessageLambda = timelineEditMessageLambda } - val roomEditMessageLambda = lambdaRecorder { _: EventId?, _: String, _: String?, _: List -> + val roomEditMessageLambda = lambdaRecorder { _: EventId?, _: String, _: String?, _: List -> Result.success(Unit) } val fakeMatrixRoom = FakeMatrixRoom( @@ -480,7 +475,7 @@ class MessageComposerPresenterTest { @Test fun `present - edit not sent message`() = runTest { - val editMessageLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String, _: String?, _: List -> + val editMessageLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String, _: String?, _: List -> Result.success(Unit) } val timeline = FakeTimeline().apply { @@ -532,7 +527,7 @@ class MessageComposerPresenterTest { @Test fun `present - reply message`() = runTest { - val replyMessageLambda = lambdaRecorder { _: EventId, _: String, _: String?, _: List, _: Boolean -> + val replyMessageLambda = lambdaRecorder { _: EventId, _: String, _: String?, _: List, _: Boolean -> Result.success(Unit) } val timeline = FakeTimeline().apply { @@ -974,34 +969,34 @@ class MessageComposerPresenterTest { // A null suggestion (no suggestion was received) returns nothing initialState.eventSink(MessageComposerEvents.SuggestionReceived(null)) - assertThat(awaitItem().memberSuggestions).isEmpty() + assertThat(awaitItem().suggestions).isEmpty() // An empty suggestion returns the room and joined members that are not the current user initialState.eventSink(MessageComposerEvents.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, ""))) - assertThat(awaitItem().memberSuggestions) - .containsExactly(ResolvedMentionSuggestion.AtRoom, ResolvedMentionSuggestion.Member(bob), ResolvedMentionSuggestion.Member(david)) + assertThat(awaitItem().suggestions) + .containsExactly(ResolvedSuggestion.AtRoom, ResolvedSuggestion.Member(bob), ResolvedSuggestion.Member(david)) // A suggestion containing a part of "room" will also return the room mention initialState.eventSink(MessageComposerEvents.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, "roo"))) - assertThat(awaitItem().memberSuggestions).containsExactly(ResolvedMentionSuggestion.AtRoom) + assertThat(awaitItem().suggestions).containsExactly(ResolvedSuggestion.AtRoom) // A non-empty suggestion will return those joined members whose user id matches it initialState.eventSink(MessageComposerEvents.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, "bob"))) - assertThat(awaitItem().memberSuggestions).containsExactly(ResolvedMentionSuggestion.Member(bob)) + assertThat(awaitItem().suggestions).containsExactly(ResolvedSuggestion.Member(bob)) // A non-empty suggestion will return those joined members whose display name matches it initialState.eventSink(MessageComposerEvents.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, "dave"))) - assertThat(awaitItem().memberSuggestions).containsExactly(ResolvedMentionSuggestion.Member(david)) + assertThat(awaitItem().suggestions).containsExactly(ResolvedSuggestion.Member(david)) // If the suggestion isn't a mention, no suggestions are returned initialState.eventSink(MessageComposerEvents.SuggestionReceived(Suggestion(0, 0, SuggestionType.Command, ""))) - assertThat(awaitItem().memberSuggestions).isEmpty() + assertThat(awaitItem().suggestions).isEmpty() // If user has no permission to send `@room` mentions, `RoomMemberSuggestion.Room` is not returned canUserTriggerRoomNotificationResult = false initialState.eventSink(MessageComposerEvents.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, ""))) - assertThat(awaitItem().memberSuggestions) - .containsExactly(ResolvedMentionSuggestion.Member(bob), ResolvedMentionSuggestion.Member(david)) + assertThat(awaitItem().suggestions) + .containsExactly(ResolvedSuggestion.Member(bob), ResolvedSuggestion.Member(david)) } } @@ -1039,13 +1034,12 @@ class MessageComposerPresenterTest { // An empty suggestion returns the joined members that are not the current user, but not the room initialState.eventSink(MessageComposerEvents.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, ""))) skipItems(1) - assertThat(awaitItem().memberSuggestions) - .containsExactly(ResolvedMentionSuggestion.Member(bob), ResolvedMentionSuggestion.Member(david)) + assertThat(awaitItem().suggestions) + .containsExactly(ResolvedSuggestion.Member(bob), ResolvedSuggestion.Member(david)) } } - @Test - fun `present - insertMention for user in rich text editor`() = runTest { + fun `present - InsertSuggestion`() = runTest { val presenter = createPresenter( coroutineScope = this, permalinkBuilder = FakePermalinkBuilder( @@ -1059,7 +1053,7 @@ class MessageComposerPresenterTest { }.test { val initialState = awaitFirstItem() initialState.textEditorState.setHtml("Hey @bo") - initialState.eventSink(MessageComposerEvents.InsertMention(ResolvedMentionSuggestion.Member(aRoomMember(userId = A_USER_ID_2)))) + initialState.eventSink(MessageComposerEvents.InsertSuggestion(ResolvedSuggestion.Member(aRoomMember(userId = A_USER_ID_2)))) assertThat(initialState.textEditorState.messageHtml()) .isEqualTo("Hey ${A_USER_ID_2.value}") @@ -1069,17 +1063,17 @@ class MessageComposerPresenterTest { @OptIn(ExperimentalCoroutinesApi::class) @Test fun `present - send messages with intentional mentions`() = runTest { - val replyMessageLambda = lambdaRecorder { _: EventId, _: String, _: String?, _: List, _: Boolean -> + val replyMessageLambda = lambdaRecorder { _: EventId, _: String, _: String?, _: List, _: Boolean -> Result.success(Unit) } - val editMessageLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String, _: String?, _: List -> + val editMessageLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String, _: String?, _: List -> Result.success(Unit) } val timeline = FakeTimeline().apply { this.replyMessageLambda = replyMessageLambda this.editMessageLambda = editMessageLambda } - val sendMessageResult = lambdaRecorder { _: String, _: String?, _: List -> + val sendMessageResult = lambdaRecorder { _: String, _: String?, _: List -> Result.success(Unit) } val room = FakeMatrixRoom( @@ -1107,7 +1101,7 @@ class MessageComposerPresenterTest { advanceUntilIdle() sendMessageResult.assertions().isCalledOnce() - .with(value(A_MESSAGE), any(), value(listOf(Mention.User(A_USER_ID)))) + .with(value(A_MESSAGE), any(), value(listOf(IntentionalMention.User(A_USER_ID)))) // Check intentional mentions on reply sent initialState.eventSink(MessageComposerEvents.SetMode(aReplyMode())) @@ -1124,7 +1118,7 @@ class MessageComposerPresenterTest { assert(replyMessageLambda) .isCalledOnce() - .with(any(), any(), any(), value(listOf(Mention.User(A_USER_ID_2))), value(false)) + .with(any(), any(), any(), value(listOf(IntentionalMention.User(A_USER_ID_2))), value(false)) // Check intentional mentions on edit message skipItems(1) @@ -1142,7 +1136,7 @@ class MessageComposerPresenterTest { assert(editMessageLambda) .isCalledOnce() - .with(any(), any(), any(), any(), value(listOf(Mention.User(A_USER_ID_3)))) + .with(any(), any(), any(), any(), value(listOf(IntentionalMention.User(A_USER_ID_3)))) skipItems(1) } @@ -1507,6 +1501,7 @@ class MessageComposerPresenterTest { analyticsService, DefaultMessageComposerContext(), TestRichTextEditorStateFactory(), + roomAliasSuggestionsDataSource = FakeRoomAliasSuggestionsDataSource(), permissionsPresenterFactory = FakePermissionsPresenterFactory(permissionPresenter), permalinkParser = permalinkParser, permalinkBuilder = permalinkBuilder, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/TestRichTextEditorStateFactory.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/TestRichTextEditorStateFactory.kt similarity index 86% rename from features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/TestRichTextEditorStateFactory.kt rename to features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/TestRichTextEditorStateFactory.kt index 921a7331fd..df5c1c6183 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/TestRichTextEditorStateFactory.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/TestRichTextEditorStateFactory.kt @@ -14,10 +14,9 @@ * limitations under the License. */ -package io.element.android.features.messages.impl.textcomposer +package io.element.android.features.messages.impl.messagecomposer import androidx.compose.runtime.Composable -import io.element.android.features.messages.impl.messagecomposer.RichTextEditorStateFactory import io.element.android.wysiwyg.compose.RichTextEditorState import io.element.android.wysiwyg.compose.rememberRichTextEditorState diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt index 887ce88d95..a1b0e73b65 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt @@ -18,7 +18,7 @@ package io.element.android.features.messages.impl.timeline import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.test.AN_EVENT_ID @@ -162,10 +162,10 @@ class TimelineControllerTest { @Test fun `test invokeOnCurrentTimeline use the detached timeline and not the live timeline`() = runTest { - val lambdaForDetached = lambdaRecorder { _: String, _: String?, _: List -> + val lambdaForDetached = lambdaRecorder { _: String, _: String?, _: List -> Result.success(Unit) } - val lambdaForLive = lambdaRecorder(ensureNeverCalled = true) { _: String, _: String?, _: List -> + val lambdaForLive = lambdaRecorder(ensureNeverCalled = true) { _: String, _: String?, _: List -> Result.success(Unit) } val liveTimeline = FakeTimeline(name = "live").apply { diff --git a/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/SharePresenter.kt b/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/SharePresenter.kt index c0ebb4ee16..4fae510f00 100644 --- a/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/SharePresenter.kt +++ b/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/SharePresenter.kt @@ -100,7 +100,7 @@ class SharePresenter @AssistedInject constructor( matrixClient.getRoom(roomId)?.sendMessage( body = text, htmlBody = null, - mentions = emptyList(), + intentionalMentions = emptyList(), )?.isSuccess.orFalse() } .all { it } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt index 5e562f43c5..a7b2bf26cf 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt @@ -25,6 +25,5 @@ interface PermalinkBuilder { } sealed class PermalinkBuilderError : Throwable() { - data object InvalidUserId : PermalinkBuilderError() - data object InvalidRoomAlias : PermalinkBuilderError() + data object InvalidData : PermalinkBuilderError() } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/Mention.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/IntentionalMention.kt similarity index 71% rename from libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/Mention.kt rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/IntentionalMention.kt index a02fedde4b..0931cf0460 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/Mention.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/IntentionalMention.kt @@ -16,12 +16,9 @@ package io.element.android.libraries.matrix.api.room -import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId -sealed interface Mention { - data class User(val userId: UserId) : Mention - data object AtRoom : Mention - data class Room(val roomId: RoomId) : Mention - data class RoomAlias(val roomAlias: RoomAlias?) : Mention +sealed interface IntentionalMention { + data class User(val userId: UserId) : IntentionalMention + data object Room : IntentionalMention } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index a469904aac..b3feb25d5f 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -129,9 +129,9 @@ interface MatrixRoom : Closeable { suspend fun userAvatarUrl(userId: UserId): Result - suspend fun sendMessage(body: String, htmlBody: String?, mentions: List): Result + suspend fun sendMessage(body: String, htmlBody: String?, intentionalMentions: List): Result - suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List): Result + suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, intentionalMentions: List): Result suspend fun sendImage( file: File, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt index f42ec5fbe9..9585b2521b 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt @@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.MediaUploadHandler import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo import kotlinx.coroutines.flow.Flow @@ -52,15 +52,24 @@ interface Timeline : AutoCloseable { fun paginationStatus(direction: PaginationDirection): StateFlow val timelineItems: Flow> - suspend fun sendMessage(body: String, htmlBody: String?, mentions: List): Result + suspend fun sendMessage( + body: String, + htmlBody: String?, + intentionalMentions: List, + ): Result - suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String?, mentions: List): Result + suspend fun editMessage( + originalEventId: EventId?, + transactionId: TransactionId?, + body: String, htmlBody: String?, + intentionalMentions: List, + ): Result suspend fun replyMessage( eventId: EventId, body: String, htmlBody: String?, - mentions: List, + intentionalMentions: List, fromNotification: Boolean = false, ): Result diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt index 30a458b28f..e3a327300f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt @@ -31,7 +31,7 @@ import javax.inject.Inject class DefaultPermalinkBuilder @Inject constructor() : PermalinkBuilder { override fun permalinkForUser(userId: UserId): Result { if (!MatrixPatterns.isUserId(userId.value)) { - return Result.failure(PermalinkBuilderError.InvalidUserId) + return Result.failure(PermalinkBuilderError.InvalidData) } return runCatching { matrixToUserPermalink(userId.value) @@ -40,7 +40,7 @@ class DefaultPermalinkBuilder @Inject constructor() : PermalinkBuilder { override fun permalinkForRoomAlias(roomAlias: RoomAlias): Result { if (!MatrixPatterns.isRoomAlias(roomAlias.value)) { - return Result.failure(PermalinkBuilderError.InvalidRoomAlias) + return Result.failure(PermalinkBuilderError.InvalidData) } return runCatching { matrixToRoomAliasPermalink(roomAlias.value) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/Mention.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/Mention.kt index 795ac2e003..85c63aebc1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/Mention.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/Mention.kt @@ -16,11 +16,11 @@ package io.element.android.libraries.matrix.impl.room -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention import org.matrix.rustcomponents.sdk.Mentions -fun List.map(): Mentions { - val hasAtRoom = any { it is Mention.AtRoom } - val userIds = filterIsInstance().map { it.userId.value } - return Mentions(userIds, hasAtRoom) +fun List.map(): Mentions { + val hasRoom = any { it is IntentionalMention.Room } + val userIds = filterIsInstance().map { it.userId.value } + return Mentions(userIds, hasRoom) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 111370dcc4..20dceeeb87 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -33,11 +33,11 @@ import io.element.android.libraries.matrix.api.media.MediaUploadHandler import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.poll.PollKind +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState -import io.element.android.libraries.matrix.api.room.Mention 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.StateEventType @@ -340,16 +340,21 @@ class RustMatrixRoom( } } - override suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List): Result = withContext(roomDispatcher) { + override suspend fun editMessage( + eventId: EventId, + body: String, + htmlBody: String?, + intentionalMentions: List + ): Result = withContext(roomDispatcher) { runCatching { - MessageEventContent.from(body, htmlBody, mentions).use { newContent -> + MessageEventContent.from(body, htmlBody, intentionalMentions).use { newContent -> innerRoom.edit(eventId.value, newContent) } } } - override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List): Result { - return liveTimeline.sendMessage(body, htmlBody, mentions) + override suspend fun sendMessage(body: String, htmlBody: String?, intentionalMentions: List): Result { + return liveTimeline.sendMessage(body, htmlBody, intentionalMentions) } override suspend fun leave(): Result = withContext(roomDispatcher) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 87fca3d395..8c774d2d29 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -26,8 +26,8 @@ import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.MediaUploadHandler import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.MatrixRoom -import io.element.android.libraries.matrix.api.room.Mention import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem @@ -263,8 +263,12 @@ class RustTimeline( } } - override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List): Result = withContext(dispatcher) { - MessageEventContent.from(body, htmlBody, mentions).use { content -> + override suspend fun sendMessage( + body: String, + htmlBody: String?, + intentionalMentions: List, + ): Result = withContext(dispatcher) { + MessageEventContent.from(body, htmlBody, intentionalMentions).use { content -> runCatching { inner.send(content) } @@ -284,13 +288,13 @@ class RustTimeline( transactionId: TransactionId?, body: String, htmlBody: String?, - mentions: List, + intentionalMentions: List, ): Result = withContext(dispatcher) { runCatching { getEventTimelineItem(originalEventId, transactionId).use { item -> inner.edit( - newContent = MessageEventContent.from(body, htmlBody, mentions), + newContent = MessageEventContent.from(body, htmlBody, intentionalMentions), item = item, ) } @@ -301,11 +305,11 @@ class RustTimeline( eventId: EventId, body: String, htmlBody: String?, - mentions: List, + intentionalMentions: List, fromNotification: Boolean, ): Result = withContext(dispatcher) { runCatching { - val msg = MessageEventContent.from(body, htmlBody, mentions) + val msg = MessageEventContent.from(body, htmlBody, intentionalMentions) inner.sendReply(msg, eventId.value) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt index e1728bb528..70de27a30d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt @@ -16,7 +16,7 @@ package io.element.android.libraries.matrix.impl.util -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.impl.room.map import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation import org.matrix.rustcomponents.sdk.messageEventContentFromHtml @@ -26,11 +26,11 @@ import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown * Creates a [RoomMessageEventContentWithoutRelation] from a body, an html body and a list of mentions. */ object MessageEventContent { - fun from(body: String, htmlBody: String?, mentions: List): RoomMessageEventContentWithoutRelation { + fun from(body: String, htmlBody: String?, intentionalMentions: List): RoomMessageEventContentWithoutRelation { return if (htmlBody != null) { messageEventContentFromHtml(body, htmlBody) } else { messageEventContentFromMarkdown(body) - }.withMentions(mentions.map()) + }.withMentions(intentionalMentions.map()) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkBuilder.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkBuilder.kt index 3510a362ec..5b18c3b175 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkBuilder.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkBuilder.kt @@ -19,10 +19,11 @@ package io.element.android.libraries.matrix.test.permalink import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder +import io.element.android.tests.testutils.lambda.lambdaError class FakePermalinkBuilder( - private val permalinkForUserLambda: (UserId) -> Result = { Result.failure(Exception("Not implemented")) }, - private val permalinkForRoomAliasLambda: (RoomAlias) -> Result = { Result.failure(Exception("Not implemented")) }, + private val permalinkForUserLambda: (UserId) -> Result = { lambdaError() }, + private val permalinkForRoomAliasLambda: (RoomAlias) -> Result = { lambdaError() }, ) : PermalinkBuilder { override fun permalinkForUser(userId: UserId): Result { return permalinkForUserLambda(userId) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 1e7eb8c003..afc6d443ed 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -35,7 +35,7 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention 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.RoomNotificationMode @@ -105,8 +105,8 @@ class FakeMatrixRoom( private val setTopicResult: (String) -> Result = { lambdaError() }, private val updateAvatarResult: (String, ByteArray) -> Result = { _, _ -> lambdaError() }, private val removeAvatarResult: () -> Result = { lambdaError() }, - private val editMessageLambda: (EventId, String, String?, List) -> Result = { _, _, _, _ -> lambdaError() }, - private val sendMessageResult: (String, String?, List) -> Result = { _, _, _ -> lambdaError() }, + private val editMessageLambda: (EventId, String, String?, List) -> Result = { _, _, _, _ -> lambdaError() }, + private val sendMessageResult: (String, String?, List) -> Result = { _, _, _ -> lambdaError() }, private val updateUserRoleResult: () -> Result = { lambdaError() }, private val toggleReactionResult: (String, EventId) -> Result = { _, _ -> lambdaError() }, private val retrySendMessageResult: (TransactionId) -> Result = { lambdaError() }, @@ -222,12 +222,12 @@ class FakeMatrixRoom( return updateUserRoleResult() } - override suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List) = simulateLongTask { - editMessageLambda(eventId, body, htmlBody, mentions) + override suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, intentionalMentions: List) = simulateLongTask { + editMessageLambda(eventId, body, htmlBody, intentionalMentions) } - override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List) = simulateLongTask { - sendMessageResult(body, htmlBody, mentions) + override suspend fun sendMessage(body: String, htmlBody: String?, intentionalMentions: List) = simulateLongTask { + sendMessageResult(body, htmlBody, intentionalMentions) } override suspend fun toggleReaction(emoji: String, eventId: EventId): Result { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt index ea9b353a67..ea28693872 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt @@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.MediaUploadHandler import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.ReceiptType @@ -60,7 +60,7 @@ class FakeTimeline( var sendMessageLambda: ( body: String, htmlBody: String?, - mentions: List, + intentionalMentions: List, ) -> Result = { _, _, _ -> Result.success(Unit) } @@ -68,8 +68,8 @@ class FakeTimeline( override suspend fun sendMessage( body: String, htmlBody: String?, - mentions: List, - ): Result = sendMessageLambda(body, htmlBody, mentions) + intentionalMentions: List, + ): Result = sendMessageLambda(body, htmlBody, intentionalMentions) var redactEventLambda: (eventId: EventId?, transactionId: TransactionId?, reason: String?) -> Result = { _, _, _ -> Result.success(true) @@ -86,7 +86,7 @@ class FakeTimeline( transactionId: TransactionId?, body: String, htmlBody: String?, - mentions: List, + intentionalMentions: List, ) -> Result = { _, _, _, _, _ -> Result.success(Unit) } @@ -96,20 +96,20 @@ class FakeTimeline( transactionId: TransactionId?, body: String, htmlBody: String?, - mentions: List, + intentionalMentions: List, ): Result = editMessageLambda( originalEventId, transactionId, body, htmlBody, - mentions + intentionalMentions ) var replyMessageLambda: ( eventId: EventId, body: String, htmlBody: String?, - mentions: List, + intentionalMentions: List, fromNotification: Boolean, ) -> Result = { _, _, _, _, _ -> Result.success(Unit) @@ -119,13 +119,13 @@ class FakeTimeline( eventId: EventId, body: String, htmlBody: String?, - mentions: List, + intentionalMentions: List, fromNotification: Boolean, ): Result = replyMessageLambda( eventId, body, htmlBody, - mentions, + intentionalMentions, fromNotification, ) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt index f5c407101e..1286f3b065 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt @@ -171,14 +171,14 @@ class NotificationBroadcastReceiverHandler @Inject constructor( eventId = threadId.asEventId(), body = message, htmlBody = null, - mentions = emptyList(), + intentionalMentions = emptyList(), fromNotification = true, ) } else { room.liveTimeline.sendMessage( body = message, htmlBody = null, - mentions = emptyList() + intentionalMentions = emptyList() ) }.onFailure { Timber.e(it, "Failed to send smart reply message") diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/markdown/MarkdownTextInput.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/markdown/MarkdownTextInput.kt index ea31f51585..d93b1f8ab0 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/markdown/MarkdownTextInput.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/markdown/MarkdownTextInput.kt @@ -111,13 +111,13 @@ fun MarkdownTextInput( state.text.update(editable, false) state.lineCount = lineCount - state.currentMentionSuggestion = editable?.checkSuggestionNeeded() - onReceiveSuggestion(state.currentMentionSuggestion) + state.currentSuggestion = editable?.checkSuggestionNeeded() + onReceiveSuggestion(state.currentSuggestion) } onSelectionChangeListener = { selStart, selEnd -> state.selection = selStart..selEnd - state.currentMentionSuggestion = editableText.checkSuggestionNeeded() - onReceiveSuggestion(state.currentMentionSuggestion) + state.currentSuggestion = editableText.checkSuggestionNeeded() + onReceiveSuggestion(state.currentSuggestion) } if (onSelectRichContent != null) { ViewCompat.setOnReceiveContentListener( diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/ResolvedMentionSuggestion.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/ResolvedSuggestion.kt similarity index 67% rename from libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/ResolvedMentionSuggestion.kt rename to libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/ResolvedSuggestion.kt index 03bc48f53d..7bb0fa6dea 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/ResolvedMentionSuggestion.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/ResolvedSuggestion.kt @@ -17,10 +17,13 @@ package io.element.android.libraries.textcomposer.mentions import androidx.compose.runtime.Immutable +import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.roomlist.RoomSummary @Immutable -sealed interface ResolvedMentionSuggestion { - data object AtRoom : ResolvedMentionSuggestion - data class Member(val roomMember: RoomMember) : ResolvedMentionSuggestion +sealed interface ResolvedSuggestion { + data object AtRoom : ResolvedSuggestion + data class Member(val roomMember: RoomMember) : ResolvedSuggestion + data class Alias(val roomAlias: RoomAlias, val roomSummary: RoomSummary) : ResolvedSuggestion } diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt index dd03c66366..f033966cdb 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt @@ -31,13 +31,14 @@ import androidx.compose.runtime.saveable.SaverScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.core.text.getSpans +import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.textcomposer.components.markdown.StableCharSequence import io.element.android.libraries.textcomposer.mentions.MentionSpan import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider -import io.element.android.libraries.textcomposer.mentions.ResolvedMentionSuggestion +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.mentions.getMentionSpans import kotlinx.parcelize.Parcelize @@ -51,16 +52,16 @@ class MarkdownTextEditorState( var hasFocus by mutableStateOf(initialFocus) var requestFocusAction by mutableStateOf({}) var lineCount by mutableIntStateOf(1) - var currentMentionSuggestion by mutableStateOf(null) + var currentSuggestion by mutableStateOf(null) - fun insertMention( - mention: ResolvedMentionSuggestion, + fun insertSuggestion( + resolvedSuggestion: ResolvedSuggestion, mentionSpanProvider: MentionSpanProvider, permalinkBuilder: PermalinkBuilder, ) { - val suggestion = currentMentionSuggestion ?: return - when (mention) { - is ResolvedMentionSuggestion.AtRoom -> { + val suggestion = currentSuggestion ?: return + when (resolvedSuggestion) { + is ResolvedSuggestion.AtRoom -> { val currentText = SpannableStringBuilder(text.value()) val replaceText = "@room" val roomPill = mentionSpanProvider.getMentionSpanFor(replaceText, "") @@ -70,10 +71,21 @@ class MarkdownTextEditorState( text.update(currentText, true) selection = IntRange(end + 1, end + 1) } - is ResolvedMentionSuggestion.Member -> { + is ResolvedSuggestion.Member -> { val currentText = SpannableStringBuilder(text.value()) - val text = mention.roomMember.displayName?.prependIndent("@") ?: mention.roomMember.userId.value - val link = permalinkBuilder.permalinkForUser(mention.roomMember.userId).getOrNull() ?: return + val text = resolvedSuggestion.roomMember.displayName?.prependIndent("@") ?: resolvedSuggestion.roomMember.userId.value + val link = permalinkBuilder.permalinkForUser(resolvedSuggestion.roomMember.userId).getOrNull() ?: return + val mentionPill = mentionSpanProvider.getMentionSpanFor(text, link) + currentText.replace(suggestion.start, suggestion.end, ". ") + val end = suggestion.start + 1 + currentText.setSpan(mentionPill, suggestion.start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + this.text.update(currentText, true) + this.selection = IntRange(end + 1, end + 1) + } + is ResolvedSuggestion.Alias -> { + val currentText = SpannableStringBuilder(text.value()) + val text = resolvedSuggestion.roomAlias.value + val link = permalinkBuilder.permalinkForRoomAlias(resolvedSuggestion.roomAlias).getOrNull() ?: return val mentionPill = mentionSpanProvider.getMentionSpanFor(text, link) currentText.replace(suggestion.start, suggestion.end, "@ ") val end = suggestion.start + 1 @@ -96,14 +108,18 @@ class MarkdownTextEditorState( val end = charSequence.getSpanEnd(mention) when (mention.type) { MentionSpan.Type.USER -> { - val link = permalinkBuilder.permalinkForUser(UserId(mention.rawValue)).getOrNull() ?: continue - replace(start, end, "[${mention.rawValue}]($link)") + permalinkBuilder.permalinkForUser(UserId(mention.rawValue)).getOrNull()?.let { link -> + replace(start, end, "[${mention.rawValue}]($link)") + } } MentionSpan.Type.EVERYONE -> { replace(start, end, "@room") } - // Nothing to do here yet - MentionSpan.Type.ROOM -> Unit + MentionSpan.Type.ROOM -> { + permalinkBuilder.permalinkForRoomAlias(RoomAlias(mention.rawValue)).getOrNull()?.let { link -> + replace(start, end, "[${mention.text}]($link)") + } + } } } } @@ -113,13 +129,13 @@ class MarkdownTextEditorState( } } - fun getMentions(): List { + fun getMentions(): List { val text = SpannableString(text.value()) val mentionSpans = text.getSpans(0, text.length) return mentionSpans.mapNotNull { mentionSpan -> when (mentionSpan.type) { - MentionSpan.Type.USER -> Mention.User(UserId(mentionSpan.rawValue)) - MentionSpan.Type.EVERYONE -> Mention.AtRoom + MentionSpan.Type.USER -> IntentionalMention.User(UserId(mentionSpan.rawValue)) + MentionSpan.Type.EVERYONE -> IntentionalMention.Room MentionSpan.Type.ROOM -> null } } diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/Message.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/Message.kt index 9467cca627..a43f17ed64 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/Message.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/Message.kt @@ -16,10 +16,10 @@ package io.element.android.libraries.textcomposer.model -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention data class Message( val html: String?, val markdown: String, - val mentions: List, + val intentionalMentions: List, ) diff --git a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/components/markdown/MarkdownTextInputTest.kt b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/components/markdown/MarkdownTextInputTest.kt index c5949a3a41..e0e83d16db 100644 --- a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/components/markdown/MarkdownTextInputTest.kt +++ b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/components/markdown/MarkdownTextInputTest.kt @@ -34,7 +34,7 @@ import io.element.android.libraries.textcomposer.components.markdown.MarkdownTex import io.element.android.libraries.textcomposer.components.markdown.aMarkdownTextEditorState import io.element.android.libraries.textcomposer.mentions.MentionSpan import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider -import io.element.android.libraries.textcomposer.mentions.ResolvedMentionSuggestion +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.MarkdownTextEditorState import io.element.android.libraries.textcomposer.model.Suggestion import io.element.android.libraries.textcomposer.model.SuggestionType @@ -157,13 +157,13 @@ class MarkdownTextInputTest { val permalinkParser = FakePermalinkParser(result = { PermalinkData.UserLink(A_SESSION_ID) }) val permalinkBuilder = FakePermalinkBuilder(permalinkForUserLambda = { Result.success("https://matrix.to/#/$A_SESSION_ID") }) val state = aMarkdownTextEditorState(initialText = "@", initialFocus = true) - state.currentMentionSuggestion = Suggestion(0, 1, SuggestionType.Mention, "") + state.currentSuggestion = Suggestion(0, 1, SuggestionType.Mention, "") rule.setMarkdownTextInput(state = state) var editor: EditText? = null rule.activityRule.scenario.onActivity { editor = it.findEditor() - state.insertMention( - ResolvedMentionSuggestion.Member(roomMember = aRoomMember()), + state.insertSuggestion( + ResolvedSuggestion.Member(roomMember = aRoomMember()), MentionSpanProvider(permalinkParser = permalinkParser), permalinkBuilder, ) diff --git a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/MentionSpanProviderTest.kt b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/IntentionalMentionSpanProviderTest.kt similarity index 98% rename from libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/MentionSpanProviderTest.kt rename to libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/IntentionalMentionSpanProviderTest.kt index b6522305af..19490d568b 100644 --- a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/MentionSpanProviderTest.kt +++ b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/IntentionalMentionSpanProviderTest.kt @@ -32,7 +32,7 @@ import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) -class MentionSpanProviderTest { +class IntentionalMentionSpanProviderTest { @JvmField @Rule val warmUpRule = WarmUpRule() diff --git a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt index b4f3c143bd..8b0e48a6df 100644 --- a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt +++ b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt @@ -22,13 +22,13 @@ import androidx.core.text.inSpans import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.permalink.PermalinkData -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.libraries.textcomposer.mentions.MentionSpan import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider -import io.element.android.libraries.textcomposer.mentions.ResolvedMentionSuggestion +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.MarkdownTextEditorState import io.element.android.libraries.textcomposer.model.Suggestion import io.element.android.libraries.textcomposer.model.SuggestionType @@ -41,11 +41,11 @@ class MarkdownTextEditorStateTest { fun `insertMention - with no currentMentionSuggestion does nothing`() { val state = MarkdownTextEditorState(initialText = "Hello @", initialFocus = true) val member = aRoomMember() - val mention = ResolvedMentionSuggestion.Member(member) + val mention = ResolvedSuggestion.Member(member) val permalinkBuilder = FakePermalinkBuilder() val mentionSpanProvider = aMentionSpanProvider() - state.insertMention(mention, mentionSpanProvider, permalinkBuilder) + state.insertSuggestion(mention, mentionSpanProvider, permalinkBuilder) assertThat(state.getMentions()).isEmpty() } @@ -53,15 +53,15 @@ class MarkdownTextEditorStateTest { @Test fun `insertMention - with member but failed PermalinkBuilder result`() { val state = MarkdownTextEditorState(initialText = "Hello @", initialFocus = true).apply { - currentMentionSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Mention, text = "") + currentSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Mention, text = "") } val member = aRoomMember() - val mention = ResolvedMentionSuggestion.Member(member) + val mention = ResolvedSuggestion.Member(member) val permalinkParser = FakePermalinkParser(result = { PermalinkData.UserLink(member.userId) }) val permalinkBuilder = FakePermalinkBuilder(permalinkForUserLambda = { Result.failure(IllegalStateException("Failed")) }) val mentionSpanProvider = aMentionSpanProvider(permalinkParser = permalinkParser) - state.insertMention(mention, mentionSpanProvider, permalinkBuilder) + state.insertSuggestion(mention, mentionSpanProvider, permalinkBuilder) val mentions = state.getMentions() assertThat(mentions).isEmpty() @@ -70,36 +70,36 @@ class MarkdownTextEditorStateTest { @Test fun `insertMention - with member`() { val state = MarkdownTextEditorState(initialText = "Hello @", initialFocus = true).apply { - currentMentionSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Mention, text = "") + currentSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Mention, text = "") } val member = aRoomMember() - val mention = ResolvedMentionSuggestion.Member(member) + val mention = ResolvedSuggestion.Member(member) val permalinkParser = FakePermalinkParser(result = { PermalinkData.UserLink(member.userId) }) val permalinkBuilder = FakePermalinkBuilder(permalinkForUserLambda = { Result.success("https://matrix.to/#/${member.userId}") }) val mentionSpanProvider = aMentionSpanProvider(permalinkParser = permalinkParser) - state.insertMention(mention, mentionSpanProvider, permalinkBuilder) + state.insertSuggestion(mention, mentionSpanProvider, permalinkBuilder) val mentions = state.getMentions() assertThat(mentions).isNotEmpty() - assertThat((mentions.firstOrNull() as? Mention.User)?.userId).isEqualTo(member.userId) + assertThat((mentions.firstOrNull() as? IntentionalMention.User)?.userId).isEqualTo(member.userId) } @Test fun `insertMention - with @room`() { val state = MarkdownTextEditorState(initialText = "Hello @", initialFocus = true).apply { - currentMentionSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Mention, text = "") + currentSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Mention, text = "") } - val mention = ResolvedMentionSuggestion.AtRoom + val mention = ResolvedSuggestion.AtRoom val permalinkBuilder = FakePermalinkBuilder() val permalinkParser = FakePermalinkParser(result = { PermalinkData.FallbackLink(Uri.EMPTY, false) }) val mentionSpanProvider = aMentionSpanProvider(permalinkParser = permalinkParser) - state.insertMention(mention, mentionSpanProvider, permalinkBuilder) + state.insertSuggestion(mention, mentionSpanProvider, permalinkBuilder) val mentions = state.getMentions() assertThat(mentions).isNotEmpty() - assertThat(mentions.firstOrNull()).isInstanceOf(Mention.AtRoom::class.java) + assertThat(mentions.firstOrNull()).isInstanceOf(IntentionalMention.Room::class.java) } @Test @@ -115,14 +115,18 @@ class MarkdownTextEditorStateTest { @Test fun `getMessageMarkdown - when there are MentionSpans returns the same text with links to the mentions`() { val text = "No mentions here" - val permalinkBuilder = FakePermalinkBuilder(permalinkForUserLambda = { Result.success("https://matrix.to/#/$it") }) + val permalinkBuilder = FakePermalinkBuilder( + permalinkForUserLambda = { Result.success("https://matrix.to/#/$it") }, + permalinkForRoomAliasLambda = { Result.success("https://matrix.to/#/$it") }, + ) val state = MarkdownTextEditorState(initialText = text, initialFocus = true) state.text.update(aMarkdownTextWithMentions(), needsDisplaying = false) val markdown = state.getMessageMarkdown(permalinkBuilder = permalinkBuilder) assertThat(markdown).isEqualTo( - "Hello [@alice:matrix.org](https://matrix.to/#/@alice:matrix.org) and everyone in @room" + "Hello [@alice:matrix.org](https://matrix.to/#/@alice:matrix.org) and everyone in @room" + + " and a room [#room:domain.org](https://matrix.to/#/#room:domain.org)" ) } @@ -141,8 +145,8 @@ class MarkdownTextEditorStateTest { val mentions = state.getMentions() assertThat(mentions).isNotEmpty() - assertThat((mentions.firstOrNull() as? Mention.User)?.userId?.value).isEqualTo("@alice:matrix.org") - assertThat(mentions.lastOrNull()).isInstanceOf(Mention.AtRoom::class.java) + assertThat((mentions.firstOrNull() as? IntentionalMention.User)?.userId?.value).isEqualTo("@alice:matrix.org") + assertThat(mentions.lastOrNull()).isInstanceOf(IntentionalMention.Room::class.java) } private fun aMentionSpanProvider( @@ -154,6 +158,7 @@ class MarkdownTextEditorStateTest { private fun aMarkdownTextWithMentions(): CharSequence { val userMentionSpan = MentionSpan("@Alice", "@alice:matrix.org", MentionSpan.Type.USER) val atRoomMentionSpan = MentionSpan("@room", "@room", MentionSpan.Type.EVERYONE) + val roomMentionSpan = MentionSpan("#room:domain.org", "#room:domain.org", MentionSpan.Type.ROOM) return buildSpannedString { append("Hello ") inSpans(userMentionSpan) { @@ -163,6 +168,10 @@ class MarkdownTextEditorStateTest { inSpans(atRoomMentionSpan) { append("@") } + append(" and a room ") + inSpans(roomMentionSpan) { + append("#room:domain.org") + } } } } From ff217d4f88cc44c6438935e2a3c39dc98cd05686 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 21 Aug 2024 13:45:00 +0000 Subject: [PATCH 139/186] Update screenshots --- ...ges.impl.mentions_MentionSuggestionsPickerView_Day_0_en.png | 3 --- ...s.impl.mentions_MentionSuggestionsPickerView_Night_0_en.png | 3 --- ...s.messages.impl.mentions_SuggestionsPickerView_Day_0_en.png | 3 +++ ...messages.impl.mentions_SuggestionsPickerView_Night_0_en.png | 3 +++ 4 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en.png deleted file mode 100644 index f9dfbe16d6..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:585d57c2b8e9a068fcd5e23ceb9e54ea4b87e7ed41035e31e13fe6869a0a6e06 -size 16842 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en.png deleted file mode 100644 index 90cb82da36..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e581b1b19e882e164faba8dbfee8b37f91391ebf4bcda69fccb66439586ee24c -size 16910 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Day_0_en.png new file mode 100644 index 0000000000..1d3db4da10 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d27b66d236df0754cc3d138e1c319223feaf1e58e1d0a11841eaec8d33af064f +size 22373 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Night_0_en.png new file mode 100644 index 0000000000..ddbe055b36 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbb94e7c3af4ca7c1bb635c314d853d2c8575ca691f515b22a29b0ce72444475 +size 22549 From 4c8f23a0cbf813b284ed4ce9af81a91ce0feb833 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 15:50:55 +0200 Subject: [PATCH 140/186] Add feature flag for room alias suggestions, disabled by default. --- .../impl/messagecomposer/MessageComposerPresenter.kt | 4 +++- .../android/libraries/featureflag/api/FeatureFlags.kt | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) 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 114a0fdb2a..358ed8033c 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 @@ -150,8 +150,10 @@ class MessageComposerPresenter @Inject constructor( } val markdownTextEditorState = rememberMarkdownTextEditorState(initialText = null, initialFocus = false) var isMentionsEnabled by remember { mutableStateOf(false) } + var isRoomAliasSuggestionsEnabled by remember { mutableStateOf(false) } LaunchedEffect(Unit) { isMentionsEnabled = featureFlagService.isFeatureEnabled(FeatureFlags.Mentions) + isRoomAliasSuggestionsEnabled = featureFlagService.isFeatureEnabled(FeatureFlags.RoomAliasSuggestions) } val cameraPermissionState = cameraPermissionPresenter.present() @@ -235,7 +237,7 @@ class MessageComposerPresenter @Inject constructor( val result = MentionSuggestionsProcessor.process( suggestion = suggestion, roomMembersState = roomMembersState, - roomAliasSuggestions = roomAliasSuggestions, + roomAliasSuggestions = if (isRoomAliasSuggestionsEnabled) roomAliasSuggestions else emptyList(), currentUserId = currentUserId, canSendRoomMention = ::canSendRoomMention, ) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index ccc910d02c..93951003f8 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -72,6 +72,13 @@ enum class FeatureFlags( defaultValue = { true }, isFinished = false, ), + RoomAliasSuggestions( + key = "feature.roomAliasSuggestions", + title = "Room alias suggestions", + description = "Type `#` to get room alias suggestions and insert them", + defaultValue = { false }, + isFinished = false, + ), MarkAsUnread( key = "feature.markAsUnread", title = "Mark as unread", From 3350b661e70ded8265be18a8ffcaedbdac45f7dd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 16:31:03 +0200 Subject: [PATCH 141/186] Fix import ordering. --- .../impl/messagecomposer/MessageComposerPresenterTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e38f7e79c4..745c45859f 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 @@ -45,9 +45,9 @@ import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder import io.element.android.libraries.matrix.api.permalink.PermalinkParser +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState -import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType From c5d1bed5b4bf3c992f22e9a71d1b09a755c3cded Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 16:32:37 +0200 Subject: [PATCH 142/186] Fix test compilation issue. --- .../NotificationBroadcastReceiverHandlerTest.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt index 40d32878df..1bddedc2e5 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt @@ -24,7 +24,7 @@ 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.api.core.asEventId -import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.test.AN_EVENT_ID @@ -337,8 +337,8 @@ class NotificationBroadcastReceiverHandlerTest { @Test fun `Test send reply`() = runTest { - val sendMessage = lambdaRecorder, Result> { _, _, _ -> Result.success(Unit) } - val replyMessage = lambdaRecorder, Boolean, Result> { _, _, _, _, _ -> Result.success(Unit) } + val sendMessage = lambdaRecorder, Result> { _, _, _ -> Result.success(Unit) } + val replyMessage = lambdaRecorder, Boolean, Result> { _, _, _, _, _ -> Result.success(Unit) } val liveTimeline = FakeTimeline().apply { sendMessageLambda = sendMessage replyMessageLambda = replyMessage @@ -363,7 +363,7 @@ class NotificationBroadcastReceiverHandlerTest { runCurrent() sendMessage.assertions() .isCalledOnce() - .with(value(A_MESSAGE), value(null), value(emptyList())) + .with(value(A_MESSAGE), value(null), value(emptyList())) onNotifiableEventReceivedResult.assertions() .isCalledOnce() replyMessage.assertions() @@ -372,7 +372,7 @@ class NotificationBroadcastReceiverHandlerTest { @Test fun `Test send reply blank message`() = runTest { - val sendMessage = lambdaRecorder, Result> { _, _, _ -> Result.success(Unit) } + val sendMessage = lambdaRecorder, Result> { _, _, _ -> Result.success(Unit) } val liveTimeline = FakeTimeline().apply { sendMessageLambda = sendMessage } @@ -396,8 +396,8 @@ class NotificationBroadcastReceiverHandlerTest { @Test fun `Test send reply to thread`() = runTest { - val sendMessage = lambdaRecorder, Result> { _, _, _ -> Result.success(Unit) } - val replyMessage = lambdaRecorder, Boolean, Result> { _, _, _, _, _ -> Result.success(Unit) } + val sendMessage = lambdaRecorder, Result> { _, _, _ -> Result.success(Unit) } + val replyMessage = lambdaRecorder, Boolean, Result> { _, _, _, _, _ -> Result.success(Unit) } val liveTimeline = FakeTimeline().apply { sendMessageLambda = sendMessage replyMessageLambda = replyMessage @@ -427,7 +427,7 @@ class NotificationBroadcastReceiverHandlerTest { .isCalledOnce() replyMessage.assertions() .isCalledOnce() - .with(value(A_THREAD_ID.asEventId()), value(A_MESSAGE), value(null), value(emptyList()), value(true)) + .with(value(A_THREAD_ID.asEventId()), value(A_MESSAGE), value(null), value(emptyList()), value(true)) } private fun createIntent( From b3e8cf443e392a193d3a8ba6ad429a5a7dc465bb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 16:59:44 +0200 Subject: [PATCH 143/186] Fix test regression. --- .../libraries/textcomposer/model/MarkdownTextEditorState.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt index f033966cdb..f1437ee1f5 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt @@ -76,7 +76,7 @@ class MarkdownTextEditorState( val text = resolvedSuggestion.roomMember.displayName?.prependIndent("@") ?: resolvedSuggestion.roomMember.userId.value val link = permalinkBuilder.permalinkForUser(resolvedSuggestion.roomMember.userId).getOrNull() ?: return val mentionPill = mentionSpanProvider.getMentionSpanFor(text, link) - currentText.replace(suggestion.start, suggestion.end, ". ") + currentText.replace(suggestion.start, suggestion.end, "@ ") val end = suggestion.start + 1 currentText.setSpan(mentionPill, suggestion.start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) this.text.update(currentText, true) @@ -87,7 +87,7 @@ class MarkdownTextEditorState( val text = resolvedSuggestion.roomAlias.value val link = permalinkBuilder.permalinkForRoomAlias(resolvedSuggestion.roomAlias).getOrNull() ?: return val mentionPill = mentionSpanProvider.getMentionSpanFor(text, link) - currentText.replace(suggestion.start, suggestion.end, "@ ") + currentText.replace(suggestion.start, suggestion.end, "# ") val end = suggestion.start + 1 currentText.setSpan(mentionPill, suggestion.start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) this.text.update(currentText, true) From c306636d564cae55e1bea973742aeb3495b33fd7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 17:27:29 +0200 Subject: [PATCH 144/186] Remove needless blank line --- .../impl/messagecomposer/RoomAliasSuggestionsDataSource.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/RoomAliasSuggestionsDataSource.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/RoomAliasSuggestionsDataSource.kt index f905c29697..860b1147cd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/RoomAliasSuggestionsDataSource.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/RoomAliasSuggestionsDataSource.kt @@ -55,4 +55,3 @@ class DefaultRoomAliasSuggestionsDataSource @Inject constructor( } } } - From 6309137a534513812f2a1bc556bd6d350ed33e0b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 17:27:55 +0200 Subject: [PATCH 145/186] Reorder imports --- .../android/libraries/matrix/test/room/FakeMatrixRoom.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index afc6d443ed..af1ad33bdc 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -31,11 +31,11 @@ import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState -import io.element.android.libraries.matrix.api.room.IntentionalMention 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.RoomNotificationMode From 5df3e6d6849d266b125704cff0432efa5838c633 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 17:41:10 +0200 Subject: [PATCH 146/186] Convert MentionSuggestionsProcessor to a class and inject it in the constructor of MessageComposerPresenter --- .../impl/mentions/MentionSuggestionsProcessor.kt | 11 +++++++---- .../impl/messagecomposer/MessageComposerPresenter.kt | 3 ++- .../features/messages/impl/MessagesPresenterTest.kt | 2 ++ .../messagecomposer/MessageComposerPresenterTest.kt | 2 ++ 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt index 4467481cb5..cc82337c9e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt @@ -26,14 +26,12 @@ import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.Suggestion import io.element.android.libraries.textcomposer.model.SuggestionType +import javax.inject.Inject /** * This class is responsible for processing mention suggestions when `@`, `/` or `#` are type in the composer. */ -object MentionSuggestionsProcessor { - // We don't want to retrieve thousands of members - private const val MAX_BATCH_ITEMS = 100 - +class MentionSuggestionsProcessor @Inject constructor() { /** * Process the mention suggestions. * @param suggestion The current suggestion input @@ -114,4 +112,9 @@ object MentionSuggestionsProcessor { } } } + + companion object { + // We don't want to retrieve thousands of members + private const val MAX_BATCH_ITEMS = 100 + } } 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 358ed8033c..323a1b2ca5 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 @@ -126,6 +126,7 @@ class MessageComposerPresenter @Inject constructor( private val mentionSpanProvider: MentionSpanProvider, private val pillificationHelper: TextPillificationHelper, private val roomMemberProfilesCache: RoomMemberProfilesCache, + private val mentionSuggestionsProcessor: MentionSuggestionsProcessor, ) : Presenter { private val cameraPermissionPresenter = permissionsPresenterFactory.create(Manifest.permission.CAMERA) private var pendingEvent: MessageComposerEvents? = null @@ -234,7 +235,7 @@ class MessageComposerPresenter @Inject constructor( merge(mentionStartTrigger, mentionCompletionTrigger) .combine(room.membersStateFlow) { suggestion, roomMembersState -> suggestions.clear() - val result = MentionSuggestionsProcessor.process( + val result = mentionSuggestionsProcessor.process( suggestion = suggestion, roomMembersState = roomMembersState, roomAliasSuggestions = if (isRoomAliasSuggestionsEnabled) roomAliasSuggestions else emptyList(), 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 9bc223c341..d7916c267b 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 @@ -28,6 +28,7 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc import io.element.android.features.messages.impl.draft.FakeComposerDraftService import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactory +import io.element.android.features.messages.impl.mentions.MentionSuggestionsProcessor import io.element.android.features.messages.impl.messagecomposer.DefaultMessageComposerContext import io.element.android.features.messages.impl.messagecomposer.FakeRoomAliasSuggestionsDataSource import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter @@ -1018,6 +1019,7 @@ class MessagesPresenterTest { mentionSpanProvider = mentionSpanProvider, pillificationHelper = FakeTextPillificationHelper(), roomMemberProfilesCache = RoomMemberProfilesCache(), + mentionSuggestionsProcessor = MentionSuggestionsProcessor(), ).apply { showTextFormatting = true isTesting = true 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 745c45859f..722eb1a85f 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 @@ -29,6 +29,7 @@ import im.vector.app.features.analytics.plan.Composer import im.vector.app.features.analytics.plan.Interaction import io.element.android.features.messages.impl.draft.ComposerDraftService import io.element.android.features.messages.impl.draft.FakeComposerDraftService +import io.element.android.features.messages.impl.mentions.MentionSuggestionsProcessor import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper import io.element.android.features.messages.impl.utils.TextPillificationHelper @@ -1510,6 +1511,7 @@ class MessageComposerPresenterTest { mentionSpanProvider = mentionSpanProvider, pillificationHelper = textPillificationHelper, roomMemberProfilesCache = roomMemberProfilesCache, + mentionSuggestionsProcessor = MentionSuggestionsProcessor(), ).apply { isTesting = true showTextFormatting = isRichTextEditorEnabled From d5feda5935a6acbd402251f310896882214304fc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 17:59:01 +0200 Subject: [PATCH 147/186] Add test on MentionSuggestionsProcessor and simplify the class. --- .../mentions/MentionSuggestionsProcessor.kt | 46 ++- .../MentionSuggestionsProcessorTest.kt | 270 ++++++++++++++++++ 2 files changed, 290 insertions(+), 26 deletions(-) create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessorTest.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt index cc82337c9e..50282ce688 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt @@ -48,35 +48,29 @@ class MentionSuggestionsProcessor @Inject constructor() { currentUserId: UserId, canSendRoomMention: suspend () -> Boolean, ): List { - val members = roomMembersState.roomMembers() - return when { - members.isNullOrEmpty() || suggestion == null -> { + suggestion ?: return emptyList() + return when (suggestion.type) { + SuggestionType.Mention -> { + // Replace suggestions + val members = roomMembersState.roomMembers() + val matchingMembers = getMemberSuggestions( + query = suggestion.text, + roomMembers = members, + currentUserId = currentUserId, + canSendRoomMention = canSendRoomMention() + ) + matchingMembers + } + SuggestionType.Room -> { + roomAliasSuggestions + .filter { it.roomAlias.value.contains(suggestion.text, ignoreCase = true) } + .map { ResolvedSuggestion.Alias(it.roomAlias, it.roomSummary) } + } + SuggestionType.Command, + is SuggestionType.Custom -> { // Clear suggestions emptyList() } - else -> { - when (suggestion.type) { - SuggestionType.Mention -> { - // Replace suggestions - val matchingMembers = getMemberSuggestions( - query = suggestion.text, - roomMembers = members, - currentUserId = currentUserId, - canSendRoomMention = canSendRoomMention() - ) - matchingMembers - } - SuggestionType.Room -> { - roomAliasSuggestions - .filter { it.roomAlias.value.contains(suggestion.text, ignoreCase = true) } - .map { ResolvedSuggestion.Alias(it.roomAlias, it.roomSummary) } - } - else -> { - // Clear suggestions - emptyList() - } - } - } } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessorTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessorTest.kt new file mode 100644 index 0000000000..78e3c44e25 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessorTest.kt @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.mentions + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.messages.impl.messagecomposer.RoomAliasSuggestion +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState +import io.element.android.libraries.matrix.api.room.RoomMembershipState +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.libraries.matrix.test.room.aRoomMember +import io.element.android.libraries.matrix.test.room.aRoomSummary +import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion +import io.element.android.libraries.textcomposer.model.Suggestion +import io.element.android.libraries.textcomposer.model.SuggestionType +import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class MentionSuggestionsProcessorTest { + private fun aMentionSuggestion(text: String) = Suggestion(0, 1, SuggestionType.Mention, text) + private fun aRoomSuggestion(text: String) = Suggestion(0, 1, SuggestionType.Room, text) + private val aCommandSuggestion = Suggestion(0, 1, SuggestionType.Command, "") + private val aCustomSuggestion = Suggestion(0, 1, SuggestionType.Custom("*"), "") + + private val mentionSuggestionsProcessor = MentionSuggestionsProcessor() + + @Test + fun `processing null suggestion will return empty suggestion`() = runTest { + val result = mentionSuggestionsProcessor.process( + suggestion = null, + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID, + canSendRoomMention = { true }, + ) + assertThat(result).isEmpty() + } + + @Test + fun `processing Command will return empty suggestion`() = runTest { + val result = mentionSuggestionsProcessor.process( + suggestion = aCommandSuggestion, + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID, + canSendRoomMention = { true }, + ) + assertThat(result).isEmpty() + } + + @Test + fun `processing Custom will return empty suggestion`() = runTest { + val result = mentionSuggestionsProcessor.process( + suggestion = aCustomSuggestion, + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID, + canSendRoomMention = { true }, + ) + assertThat(result).isEmpty() + } + + @Test + fun `processing Mention suggestion with not loaded members will return empty suggestion`() = runTest { + val result = mentionSuggestionsProcessor.process( + suggestion = aMentionSuggestion(""), + roomMembersState = MatrixRoomMembersState.Unknown, + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID, + canSendRoomMention = { true }, + ) + assertThat(result).isEmpty() + } + + @Test + fun `processing Mention suggestion with no members will return empty suggestion`() = runTest { + val result = mentionSuggestionsProcessor.process( + suggestion = aMentionSuggestion(""), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID, + canSendRoomMention = { true }, + ) + assertThat(result).isEmpty() + } + + @Test + fun `processing Room suggestion with no aliases will return empty suggestion`() = runTest { + val result = mentionSuggestionsProcessor.process( + suggestion = aRoomSuggestion(""), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID, + canSendRoomMention = { true }, + ) + assertThat(result).isEmpty() + } + + @Test + fun `processing Room suggestion with aliases ignoring cases will return a suggestion`() = runTest { + val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS) + val result = mentionSuggestionsProcessor.process( + suggestion = aRoomSuggestion("ALI"), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()), + roomAliasSuggestions = listOf(RoomAliasSuggestion(A_ROOM_ALIAS, aRoomSummary)), + currentUserId = A_USER_ID, + canSendRoomMention = { true }, + ) + assertThat(result).isEqualTo( + listOf( + ResolvedSuggestion.Alias(A_ROOM_ALIAS, aRoomSummary) + ) + ) + } + + @Test + fun `processing Room suggestion with aliases will return a suggestion`() = runTest { + val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS) + val result = mentionSuggestionsProcessor.process( + suggestion = aRoomSuggestion("ali"), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()), + roomAliasSuggestions = listOf(RoomAliasSuggestion(A_ROOM_ALIAS, aRoomSummary)), + currentUserId = A_USER_ID, + canSendRoomMention = { true }, + ) + assertThat(result).isEqualTo( + listOf( + ResolvedSuggestion.Alias(A_ROOM_ALIAS, aRoomSummary) + ) + ) + } + + @Test + fun `processing Room suggestion with aliases not found will return no suggestions`() = runTest { + val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS) + val result = mentionSuggestionsProcessor.process( + suggestion = aRoomSuggestion("tot"), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()), + roomAliasSuggestions = listOf(RoomAliasSuggestion(A_ROOM_ALIAS, aRoomSummary)), + currentUserId = A_USER_ID, + canSendRoomMention = { true }, + ) + assertThat(result).isEmpty() + } + + @Test + fun `processing Mention suggestion with return matching matrix Id`() = runTest { + val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = null) + val result = mentionSuggestionsProcessor.process( + suggestion = aMentionSuggestion("ali"), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID_2, + canSendRoomMention = { true }, + ) + assertThat(result).isEqualTo( + listOf( + ResolvedSuggestion.Member(aRoomMember) + ) + ) + } + + @Test + fun `processing Mention suggestion with not return the current user`() = runTest { + val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = null) + val result = mentionSuggestionsProcessor.process( + suggestion = aMentionSuggestion("ali"), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), + roomAliasSuggestions = emptyList(), + currentUserId = UserId("@alice:server.org"), + canSendRoomMention = { true }, + ) + assertThat(result).isEmpty() + } + + @Test + fun `processing Mention suggestion with return empty list if there is no matches`() = runTest { + val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "alice") + val result = mentionSuggestionsProcessor.process( + suggestion = aMentionSuggestion("bo"), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID_2, + canSendRoomMention = { true }, + ) + assertThat(result).isEmpty() + } + + @Test + fun `processing Mention suggestion with not return not joined member`() = runTest { + val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), membership = RoomMembershipState.INVITE) + val result = mentionSuggestionsProcessor.process( + suggestion = aMentionSuggestion("ali"), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID_2, + canSendRoomMention = { true }, + ) + assertThat(result).isEmpty() + } + + @Test + fun `processing Mention suggestion with return matching display name`() = runTest { + val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "bob") + val result = mentionSuggestionsProcessor.process( + suggestion = aMentionSuggestion("bo"), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID_2, + canSendRoomMention = { true }, + ) + assertThat(result).isEqualTo( + listOf( + ResolvedSuggestion.Member(aRoomMember) + ) + ) + } + + @Test + fun `processing Mention suggestion with return matching display name and room if allowed`() = runTest { + val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "ro") + val result = mentionSuggestionsProcessor.process( + suggestion = aMentionSuggestion("ro"), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID_2, + canSendRoomMention = { true }, + ) + assertThat(result).isEqualTo( + listOf( + ResolvedSuggestion.AtRoom, + ResolvedSuggestion.Member(aRoomMember), + ) + ) + } + + @Test + fun `processing Mention suggestion with return matching display name but not room if not allowed`() = runTest { + val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "ro") + val result = mentionSuggestionsProcessor.process( + suggestion = aMentionSuggestion("ro"), + roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID_2, + canSendRoomMention = { false }, + ) + assertThat(result).isEqualTo( + listOf( + ResolvedSuggestion.Member(aRoomMember), + ) + ) + } +} From a6cf231322d96c4e19d60cbe5c21774aefe47ba3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 18:25:41 +0200 Subject: [PATCH 148/186] Add unit test for DefaultRoomAliasSuggestionsDataSource --- ...faultRoomAliasSuggestionsDataSourceTest.kt | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/DefaultRoomAliasSuggestionsDataSourceTest.kt diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/DefaultRoomAliasSuggestionsDataSourceTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/DefaultRoomAliasSuggestionsDataSourceTest.kt new file mode 100644 index 0000000000..57d33ef244 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/DefaultRoomAliasSuggestionsDataSourceTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.messagecomposer + +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS +import io.element.android.libraries.matrix.test.A_ROOM_ID_2 +import io.element.android.libraries.matrix.test.room.aRoomSummary +import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class DefaultRoomAliasSuggestionsDataSourceTest { + @Test + fun `DefaultRoomAliasSuggestionsDataSource must emit a list of room alias suggestions`() = runTest { + val roomListService = FakeRoomListService() + val sut = DefaultRoomAliasSuggestionsDataSource( + roomListService + ) + val aRoomSummaryWithAnAlias = aRoomSummary( + canonicalAlias = A_ROOM_ALIAS + ) + sut.getAllRoomAliasSuggestions().test { + assertThat(awaitItem()).isEmpty() + roomListService.postAllRooms( + listOf( + aRoomSummary(roomId = A_ROOM_ID_2, canonicalAlias = null), + aRoomSummaryWithAnAlias, + ) + ) + assertThat(awaitItem()).isEqualTo( + listOf( + RoomAliasSuggestion( + roomAlias = A_ROOM_ALIAS, + roomSummary = aRoomSummaryWithAnAlias + ) + ) + ) + } + } +} From 2488ea6c98b9acf4637e6650bc12963f4ec7fcdf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 18:35:23 +0200 Subject: [PATCH 149/186] Add missing test for MarkdownTextEditorState --- .../impl/model/MarkdownTextEditorStateTest.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt index 8b0e48a6df..a6dc1a88f3 100644 --- a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt +++ b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt @@ -21,11 +21,14 @@ import androidx.core.text.buildSpannedString import androidx.core.text.inSpans import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.room.IntentionalMention +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser import io.element.android.libraries.matrix.test.room.aRoomMember +import io.element.android.libraries.matrix.test.room.aRoomSummary import io.element.android.libraries.textcomposer.mentions.MentionSpan import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion @@ -37,6 +40,40 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class MarkdownTextEditorStateTest { + @Test + fun `insertMention - room alias - getMentions return empty list`() { + val state = MarkdownTextEditorState(initialText = "Hello @", initialFocus = true) + val suggestion = ResolvedSuggestion.Alias(A_ROOM_ALIAS, aRoomSummary(canonicalAlias = A_ROOM_ALIAS)) + val permalinkBuilder = FakePermalinkBuilder() + val mentionSpanProvider = aMentionSpanProvider() + state.insertSuggestion(suggestion, mentionSpanProvider, permalinkBuilder) + assertThat(state.getMentions()).isEmpty() + } + + @Test + fun `insertMention - room alias - with member but failed PermalinkBuilder result`() { + val state = MarkdownTextEditorState(initialText = "Hello #", initialFocus = true).apply { + currentSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Room, text = "") + } + val suggestion = ResolvedSuggestion.Alias(A_ROOM_ALIAS, aRoomSummary(canonicalAlias = A_ROOM_ALIAS)) + val permalinkParser = FakePermalinkParser(result = { PermalinkData.RoomLink(A_ROOM_ALIAS.toRoomIdOrAlias()) }) + val permalinkBuilder = FakePermalinkBuilder(permalinkForRoomAliasLambda = { Result.failure(IllegalStateException("Failed")) }) + val mentionSpanProvider = aMentionSpanProvider(permalinkParser = permalinkParser) + state.insertSuggestion(suggestion, mentionSpanProvider, permalinkBuilder) + } + + @Test + fun `insertMention - room alias`() { + val state = MarkdownTextEditorState(initialText = "Hello #", initialFocus = true).apply { + currentSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Room, text = "") + } + val suggestion = ResolvedSuggestion.Alias(A_ROOM_ALIAS, aRoomSummary(canonicalAlias = A_ROOM_ALIAS)) + val permalinkParser = FakePermalinkParser(result = { PermalinkData.RoomLink(A_ROOM_ALIAS.toRoomIdOrAlias()) }) + val permalinkBuilder = FakePermalinkBuilder(permalinkForRoomAliasLambda = { Result.success("https://matrix.to/#/${A_ROOM_ALIAS.value}") }) + val mentionSpanProvider = aMentionSpanProvider(permalinkParser = permalinkParser) + state.insertSuggestion(suggestion, mentionSpanProvider, permalinkBuilder) + } + @Test fun `insertMention - with no currentMentionSuggestion does nothing`() { val state = MarkdownTextEditorState(initialText = "Hello @", initialFocus = true) From b112713d6960c06b3d177c9cd6b34d87e2e94bed Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 21 Aug 2024 18:36:06 +0200 Subject: [PATCH 150/186] Rename test because method has been renamed. --- .../impl/model/MarkdownTextEditorStateTest.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt index a6dc1a88f3..3cd714f950 100644 --- a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt +++ b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt @@ -51,7 +51,7 @@ class MarkdownTextEditorStateTest { } @Test - fun `insertMention - room alias - with member but failed PermalinkBuilder result`() { + fun `insertSuggestion - room alias - with member but failed PermalinkBuilder result`() { val state = MarkdownTextEditorState(initialText = "Hello #", initialFocus = true).apply { currentSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Room, text = "") } @@ -63,7 +63,7 @@ class MarkdownTextEditorStateTest { } @Test - fun `insertMention - room alias`() { + fun `insertSuggestion - room alias`() { val state = MarkdownTextEditorState(initialText = "Hello #", initialFocus = true).apply { currentSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Room, text = "") } @@ -75,7 +75,7 @@ class MarkdownTextEditorStateTest { } @Test - fun `insertMention - with no currentMentionSuggestion does nothing`() { + fun `insertSuggestion - with no currentMentionSuggestion does nothing`() { val state = MarkdownTextEditorState(initialText = "Hello @", initialFocus = true) val member = aRoomMember() val mention = ResolvedSuggestion.Member(member) @@ -88,7 +88,7 @@ class MarkdownTextEditorStateTest { } @Test - fun `insertMention - with member but failed PermalinkBuilder result`() { + fun `insertSuggestion - with member but failed PermalinkBuilder result`() { val state = MarkdownTextEditorState(initialText = "Hello @", initialFocus = true).apply { currentSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Mention, text = "") } @@ -105,7 +105,7 @@ class MarkdownTextEditorStateTest { } @Test - fun `insertMention - with member`() { + fun `insertSuggestion - with member`() { val state = MarkdownTextEditorState(initialText = "Hello @", initialFocus = true).apply { currentSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Mention, text = "") } @@ -123,7 +123,7 @@ class MarkdownTextEditorStateTest { } @Test - fun `insertMention - with @room`() { + fun `insertSuggestion - with @room`() { val state = MarkdownTextEditorState(initialText = "Hello @", initialFocus = true).apply { currentSuggestion = Suggestion(start = 6, end = 7, type = SuggestionType.Mention, text = "") } From ebd8120d2e7369a0cebd62dc7bf3eb236c7b1dc5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:47:16 +0000 Subject: [PATCH 151/186] Update dependency androidx.compose:compose-bom to v2024.08.00 --- 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 9efb6341b2..1339d3bf11 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ media3 = "1.4.0" camera = "1.3.4" # Compose -compose_bom = "2024.06.00" +compose_bom = "2024.08.00" composecompiler = "1.5.15" # Coroutines From e6ab680f91704ae8fead5b4dbc462871a798dbd7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 05:29:39 +0000 Subject: [PATCH 152/186] Update telephoto to v0.13.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 9efb6341b2..77417a51d3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,7 +45,7 @@ showkase = "1.0.3" appyx = "1.4.0" sqldelight = "2.0.2" wysiwyg = "2.37.8" -telephoto = "0.12.1" +telephoto = "0.13.0" # DI dagger = "2.52" From 48ea51663938d2f54b35bde0d839fc95b93c56e1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Aug 2024 13:24:57 +0200 Subject: [PATCH 153/186] Rename `MentionSuggestionsProcessor` to `SuggestionsProcessor` since it's not only used for mentions. --- ...nsProcessor.kt => SuggestionsProcessor.kt} | 8 ++--- .../MessageComposerPresenter.kt | 6 ++-- .../messages/impl/MessagesPresenterTest.kt | 4 +-- ...sorTest.kt => SuggestionsProcessorTest.kt} | 36 +++++++++---------- .../MessageComposerPresenterTest.kt | 4 +-- 5 files changed, 29 insertions(+), 29 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/{MentionSuggestionsProcessor.kt => SuggestionsProcessor.kt} (94%) rename features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/{MentionSuggestionsProcessorTest.kt => SuggestionsProcessorTest.kt} (90%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessor.kt similarity index 94% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessor.kt index 50282ce688..4156625a6f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessor.kt @@ -29,17 +29,17 @@ import io.element.android.libraries.textcomposer.model.SuggestionType import javax.inject.Inject /** - * This class is responsible for processing mention suggestions when `@`, `/` or `#` are type in the composer. + * This class is responsible for processing suggestions when `@`, `/` or `#` are type in the composer. */ -class MentionSuggestionsProcessor @Inject constructor() { +class SuggestionsProcessor @Inject constructor() { /** - * Process the mention suggestions. + * Process the suggestion. * @param suggestion The current suggestion input * @param roomMembersState The room members state, it contains the current users in the room * @param roomAliasSuggestions The available room alias suggestions * @param currentUserId The current user id * @param canSendRoomMention Should return true if the current user can send room mentions - * @return The list of mentions to display + * @return The list of suggestions to display */ suspend fun process( suggestion: Suggestion?, 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 323a1b2ca5..199f759f98 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 @@ -40,7 +40,7 @@ import im.vector.app.features.analytics.plan.Interaction import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError import io.element.android.features.messages.impl.draft.ComposerDraftService -import io.element.android.features.messages.impl.mentions.MentionSuggestionsProcessor +import io.element.android.features.messages.impl.mentions.SuggestionsProcessor import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.utils.TextPillificationHelper import io.element.android.libraries.architecture.Presenter @@ -126,7 +126,7 @@ class MessageComposerPresenter @Inject constructor( private val mentionSpanProvider: MentionSpanProvider, private val pillificationHelper: TextPillificationHelper, private val roomMemberProfilesCache: RoomMemberProfilesCache, - private val mentionSuggestionsProcessor: MentionSuggestionsProcessor, + private val suggestionsProcessor: SuggestionsProcessor, ) : Presenter { private val cameraPermissionPresenter = permissionsPresenterFactory.create(Manifest.permission.CAMERA) private var pendingEvent: MessageComposerEvents? = null @@ -235,7 +235,7 @@ class MessageComposerPresenter @Inject constructor( merge(mentionStartTrigger, mentionCompletionTrigger) .combine(room.membersStateFlow) { suggestion, roomMembersState -> suggestions.clear() - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = suggestion, roomMembersState = roomMembersState, roomAliasSuggestions = if (isRoomAliasSuggestionsEnabled) roomAliasSuggestions else emptyList(), 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 d7916c267b..43ffccc467 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 @@ -28,7 +28,7 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc import io.element.android.features.messages.impl.draft.FakeComposerDraftService import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactory -import io.element.android.features.messages.impl.mentions.MentionSuggestionsProcessor +import io.element.android.features.messages.impl.mentions.SuggestionsProcessor import io.element.android.features.messages.impl.messagecomposer.DefaultMessageComposerContext import io.element.android.features.messages.impl.messagecomposer.FakeRoomAliasSuggestionsDataSource import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter @@ -1019,7 +1019,7 @@ class MessagesPresenterTest { mentionSpanProvider = mentionSpanProvider, pillificationHelper = FakeTextPillificationHelper(), roomMemberProfilesCache = RoomMemberProfilesCache(), - mentionSuggestionsProcessor = MentionSuggestionsProcessor(), + suggestionsProcessor = SuggestionsProcessor(), ).apply { showTextFormatting = true isTesting = true diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessorTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessorTest.kt similarity index 90% rename from features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessorTest.kt rename to features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessorTest.kt index 78e3c44e25..61297d29d5 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsProcessorTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessorTest.kt @@ -33,17 +33,17 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.test.runTest import org.junit.Test -class MentionSuggestionsProcessorTest { +class SuggestionsProcessorTest { private fun aMentionSuggestion(text: String) = Suggestion(0, 1, SuggestionType.Mention, text) private fun aRoomSuggestion(text: String) = Suggestion(0, 1, SuggestionType.Room, text) private val aCommandSuggestion = Suggestion(0, 1, SuggestionType.Command, "") private val aCustomSuggestion = Suggestion(0, 1, SuggestionType.Custom("*"), "") - private val mentionSuggestionsProcessor = MentionSuggestionsProcessor() + private val suggestionsProcessor = SuggestionsProcessor() @Test fun `processing null suggestion will return empty suggestion`() = runTest { - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = null, roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())), roomAliasSuggestions = emptyList(), @@ -55,7 +55,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Command will return empty suggestion`() = runTest { - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aCommandSuggestion, roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())), roomAliasSuggestions = emptyList(), @@ -67,7 +67,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Custom will return empty suggestion`() = runTest { - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aCustomSuggestion, roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())), roomAliasSuggestions = emptyList(), @@ -79,7 +79,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Mention suggestion with not loaded members will return empty suggestion`() = runTest { - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aMentionSuggestion(""), roomMembersState = MatrixRoomMembersState.Unknown, roomAliasSuggestions = emptyList(), @@ -91,7 +91,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Mention suggestion with no members will return empty suggestion`() = runTest { - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aMentionSuggestion(""), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()), roomAliasSuggestions = emptyList(), @@ -103,7 +103,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Room suggestion with no aliases will return empty suggestion`() = runTest { - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aRoomSuggestion(""), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()), roomAliasSuggestions = emptyList(), @@ -116,7 +116,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Room suggestion with aliases ignoring cases will return a suggestion`() = runTest { val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS) - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aRoomSuggestion("ALI"), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()), roomAliasSuggestions = listOf(RoomAliasSuggestion(A_ROOM_ALIAS, aRoomSummary)), @@ -133,7 +133,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Room suggestion with aliases will return a suggestion`() = runTest { val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS) - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aRoomSuggestion("ali"), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()), roomAliasSuggestions = listOf(RoomAliasSuggestion(A_ROOM_ALIAS, aRoomSummary)), @@ -150,7 +150,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Room suggestion with aliases not found will return no suggestions`() = runTest { val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS) - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aRoomSuggestion("tot"), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()), roomAliasSuggestions = listOf(RoomAliasSuggestion(A_ROOM_ALIAS, aRoomSummary)), @@ -163,7 +163,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Mention suggestion with return matching matrix Id`() = runTest { val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = null) - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aMentionSuggestion("ali"), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), roomAliasSuggestions = emptyList(), @@ -180,7 +180,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Mention suggestion with not return the current user`() = runTest { val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = null) - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aMentionSuggestion("ali"), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), roomAliasSuggestions = emptyList(), @@ -193,7 +193,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Mention suggestion with return empty list if there is no matches`() = runTest { val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "alice") - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aMentionSuggestion("bo"), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), roomAliasSuggestions = emptyList(), @@ -206,7 +206,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Mention suggestion with not return not joined member`() = runTest { val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), membership = RoomMembershipState.INVITE) - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aMentionSuggestion("ali"), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), roomAliasSuggestions = emptyList(), @@ -219,7 +219,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Mention suggestion with return matching display name`() = runTest { val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "bob") - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aMentionSuggestion("bo"), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), roomAliasSuggestions = emptyList(), @@ -236,7 +236,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Mention suggestion with return matching display name and room if allowed`() = runTest { val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "ro") - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aMentionSuggestion("ro"), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), roomAliasSuggestions = emptyList(), @@ -254,7 +254,7 @@ class MentionSuggestionsProcessorTest { @Test fun `processing Mention suggestion with return matching display name but not room if not allowed`() = runTest { val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "ro") - val result = mentionSuggestionsProcessor.process( + val result = suggestionsProcessor.process( suggestion = aMentionSuggestion("ro"), roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)), roomAliasSuggestions = emptyList(), 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 722eb1a85f..bd84e8f785 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 @@ -29,7 +29,7 @@ import im.vector.app.features.analytics.plan.Composer import im.vector.app.features.analytics.plan.Interaction import io.element.android.features.messages.impl.draft.ComposerDraftService import io.element.android.features.messages.impl.draft.FakeComposerDraftService -import io.element.android.features.messages.impl.mentions.MentionSuggestionsProcessor +import io.element.android.features.messages.impl.mentions.SuggestionsProcessor import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper import io.element.android.features.messages.impl.utils.TextPillificationHelper @@ -1511,7 +1511,7 @@ class MessageComposerPresenterTest { mentionSpanProvider = mentionSpanProvider, pillificationHelper = textPillificationHelper, roomMemberProfilesCache = roomMemberProfilesCache, - mentionSuggestionsProcessor = MentionSuggestionsProcessor(), + suggestionsProcessor = SuggestionsProcessor(), ).apply { isTesting = true showTextFormatting = isRichTextEditorEnabled From dbe73076ff453684a3feb89925fd6a9d93aed49a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Aug 2024 13:25:51 +0200 Subject: [PATCH 154/186] rename test function. --- .../DefaultRoomAliasSuggestionsDataSourceTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/DefaultRoomAliasSuggestionsDataSourceTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/DefaultRoomAliasSuggestionsDataSourceTest.kt index 57d33ef244..4fa976fbb4 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/DefaultRoomAliasSuggestionsDataSourceTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/DefaultRoomAliasSuggestionsDataSourceTest.kt @@ -27,7 +27,7 @@ import org.junit.Test class DefaultRoomAliasSuggestionsDataSourceTest { @Test - fun `DefaultRoomAliasSuggestionsDataSource must emit a list of room alias suggestions`() = runTest { + fun `getAllRoomAliasSuggestions must emit a list of room alias suggestions`() = runTest { val roomListService = FakeRoomListService() val sut = DefaultRoomAliasSuggestionsDataSource( roomListService From 811abe7755cfb61a48b74e421493107e45569b96 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Aug 2024 13:31:58 +0200 Subject: [PATCH 155/186] Move package `io.element.android.features.messages.impl.mentions` to `io.element.android.features.messages.impl.messagecomposer.suggestions` --- .../io/element/android/features/messages/impl/MessagesView.kt | 2 +- .../messages/impl/messagecomposer/MessageComposerPresenter.kt | 2 +- .../suggestions}/SuggestionsPickerView.kt | 2 +- .../suggestions}/SuggestionsProcessor.kt | 2 +- .../android/features/messages/impl/MessagesPresenterTest.kt | 2 +- .../impl/messagecomposer/MessageComposerPresenterTest.kt | 2 +- .../suggestions}/SuggestionsProcessorTest.kt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/{mentions => messagecomposer/suggestions}/SuggestionsPickerView.kt (98%) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/{mentions => messagecomposer/suggestions}/SuggestionsProcessor.kt (98%) rename features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/{mentions => messagecomposer/suggestions}/SuggestionsProcessorTest.kt (99%) 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 7d883894b0..f1f8b844ef 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 @@ -66,11 +66,11 @@ 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.attachments.Attachment -import io.element.android.features.messages.impl.mentions.SuggestionsPickerView import io.element.android.features.messages.impl.messagecomposer.AttachmentsBottomSheet import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerView +import io.element.android.features.messages.impl.messagecomposer.suggestions.SuggestionsPickerView import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerView import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerViewDefaults 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 199f759f98..8f01f15542 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 @@ -40,7 +40,7 @@ import im.vector.app.features.analytics.plan.Interaction import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError import io.element.android.features.messages.impl.draft.ComposerDraftService -import io.element.android.features.messages.impl.mentions.SuggestionsProcessor +import io.element.android.features.messages.impl.messagecomposer.suggestions.SuggestionsProcessor import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.utils.TextPillificationHelper import io.element.android.libraries.architecture.Presenter diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsPickerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt similarity index 98% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsPickerView.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt index f9adc75c20..fe01ab9479 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsPickerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.messages.impl.mentions +package io.element.android.features.messages.impl.messagecomposer.suggestions import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessor.kt similarity index 98% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessor.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessor.kt index 4156625a6f..171f4a2713 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessor.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.messages.impl.mentions +package io.element.android.features.messages.impl.messagecomposer.suggestions import io.element.android.features.messages.impl.messagecomposer.RoomAliasSuggestion import io.element.android.libraries.core.data.filterUpTo 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 43ffccc467..c9700a60bd 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 @@ -28,11 +28,11 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc import io.element.android.features.messages.impl.draft.FakeComposerDraftService import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactory -import io.element.android.features.messages.impl.mentions.SuggestionsProcessor import io.element.android.features.messages.impl.messagecomposer.DefaultMessageComposerContext import io.element.android.features.messages.impl.messagecomposer.FakeRoomAliasSuggestionsDataSource import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter import io.element.android.features.messages.impl.messagecomposer.TestRichTextEditorStateFactory +import io.element.android.features.messages.impl.messagecomposer.suggestions.SuggestionsProcessor import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.timeline.TimelineItemIndexer 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 bd84e8f785..632f529632 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 @@ -29,7 +29,7 @@ import im.vector.app.features.analytics.plan.Composer import im.vector.app.features.analytics.plan.Interaction import io.element.android.features.messages.impl.draft.ComposerDraftService import io.element.android.features.messages.impl.draft.FakeComposerDraftService -import io.element.android.features.messages.impl.mentions.SuggestionsProcessor +import io.element.android.features.messages.impl.messagecomposer.suggestions.SuggestionsProcessor import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper import io.element.android.features.messages.impl.utils.TextPillificationHelper diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessorTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessorTest.kt similarity index 99% rename from features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessorTest.kt rename to features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessorTest.kt index 61297d29d5..c3f7806cc4 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/mentions/SuggestionsProcessorTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessorTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.messages.impl.mentions +package io.element.android.features.messages.impl.messagecomposer.suggestions import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.messagecomposer.RoomAliasSuggestion From 8574340717f0955ed34008983c05729cab2f476c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Aug 2024 13:39:25 +0200 Subject: [PATCH 156/186] Use extension `getAvatarData` --- .../suggestions/SuggestionsPickerView.kt | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt index fe01ab9479..c52ef4771c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt @@ -46,6 +46,7 @@ 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.RoomMembershipState import io.element.android.libraries.matrix.ui.components.aRoomSummaryDetails +import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -103,25 +104,14 @@ private fun SuggestionItemView( val avatarSize = AvatarSize.Suggestion val avatarData = when (suggestion) { is ResolvedSuggestion.AtRoom -> roomAvatar?.copy(size = avatarSize) ?: AvatarData(roomId, roomName, null, avatarSize) - is ResolvedSuggestion.Member -> AvatarData( - suggestion.roomMember.userId.value, - suggestion.roomMember.displayName, - suggestion.roomMember.avatarUrl, - avatarSize, - ) - is ResolvedSuggestion.Alias -> AvatarData( - suggestion.roomSummary.roomId.value, - suggestion.roomSummary.name, - suggestion.roomSummary.avatarUrl, - avatarSize, - ) + is ResolvedSuggestion.Member -> suggestion.roomMember.getAvatarData(avatarSize) + is ResolvedSuggestion.Alias -> suggestion.roomSummary.getAvatarData(avatarSize) } val title = when (suggestion) { is ResolvedSuggestion.AtRoom -> stringResource(R.string.screen_room_mentions_at_room_title) is ResolvedSuggestion.Member -> suggestion.roomMember.displayName is ResolvedSuggestion.Alias -> suggestion.roomSummary.name } - val subtitle = when (suggestion) { is ResolvedSuggestion.AtRoom -> "@room" is ResolvedSuggestion.Member -> suggestion.roomMember.userId.value From e704af44bfbbc44ef21c42de87ec0b589a65c4a4 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 22 Aug 2024 11:54:08 +0000 Subject: [PATCH 157/186] Update screenshots --- ...essagecomposer.suggestions_SuggestionsPickerView_Day_0_en.png} | 0 ...sagecomposer.suggestions_SuggestionsPickerView_Night_0_en.png} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/uitests/src/test/snapshots/images/{features.messages.impl.mentions_SuggestionsPickerView_Day_0_en.png => features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en.png} (100%) rename tests/uitests/src/test/snapshots/images/{features.messages.impl.mentions_SuggestionsPickerView_Night_0_en.png => features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en.png} (100%) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Day_0_en.png rename to tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.messages.impl.mentions_SuggestionsPickerView_Night_0_en.png rename to tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en.png From 2678834cc0e5425265d53f6eb546a0a9c2beea58 Mon Sep 17 00:00:00 2001 From: networkException Date: Thu, 22 Aug 2024 14:47:13 +0200 Subject: [PATCH 158/186] Fix broken direct room member for rooms with old users that left (#3324) This patch fixes getDirectRoomMember not respecting direct rooms with more than two members total but only two active. This commonly occurs when users migrate to a new account by adding a new account to rooms and leaving with the old one. Other parts of the codebase (such as the people room list filter) already respect the active member count of a room instead of the total (historic) number of unique members. This fixes the room details screen not showing up correctly, for example missing the avatar cluster. Signed-off-by: networkException --- .../android/libraries/matrix/ui/room/MatrixRoomMembers.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt index 38fed2a60c..c04406228f 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt @@ -58,6 +58,7 @@ fun MatrixRoom.getDirectRoomMember(roomMembersState: MatrixRoomMembersState): St return remember(roomMembersState) { derivedStateOf { roomMembers + ?.filter { it.membership.isActive() } ?.takeIf { it.size == 2 && isDirect && isEncrypted } ?.find { it.userId != sessionId } } From a27e317207a10aba90efdf0de6c0b92827fa41b5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Aug 2024 15:01:00 +0200 Subject: [PATCH 159/186] Remove unused code. --- .../android/libraries/matrix/ui/room/MatrixRoomMembers.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt index c04406228f..2dbbe70f32 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt @@ -46,12 +46,6 @@ fun getRoomMemberAsState(roomMembersState: MatrixRoomMembersState, userId: UserI } } -@Composable -fun MatrixRoom.getDirectRoomMember(): State { - val roomMembersState by membersStateFlow.collectAsState() - return getDirectRoomMember(roomMembersState = roomMembersState) -} - @Composable fun MatrixRoom.getDirectRoomMember(roomMembersState: MatrixRoomMembersState): State { val roomMembers = roomMembersState.roomMembers() From 0b494b01da7a8c99360bc6d7454bab872afbabce Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Aug 2024 15:20:37 +0200 Subject: [PATCH 160/186] Add test on extension MatrixRoom.getDirectRoomMember --- .../matrix/ui/room/MatrixRoomMembersTest.kt | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembersTest.kt diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembersTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembersTest.kt new file mode 100644 index 0000000000..246f4f4fd5 --- /dev/null +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembersTest.kt @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.ui.room + +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState +import io.element.android.libraries.matrix.api.room.RoomMembershipState +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.libraries.matrix.test.A_USER_ID_3 +import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.matrix.test.room.aRoomMember +import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class MatrixRoomMembersTest { + private val roomMember1 = aRoomMember(A_USER_ID) + private val roomMember2 = aRoomMember(A_USER_ID_2) + private val roomMember3 = aRoomMember(A_USER_ID_3) + + @Test + fun `getDirectRoomMember emits other member for encrypted DM with 2 joined members`() = runTest { + val matrixRoom = FakeMatrixRoom( + sessionId = A_USER_ID, + isEncrypted = true, + isDirect = true, + ) + moleculeFlow(RecompositionMode.Immediate) { + matrixRoom.getDirectRoomMember( + MatrixRoomMembersState.Ready(persistentListOf(roomMember1, roomMember2)) + ) + }.test { + assertThat(awaitItem().value).isEqualTo(roomMember2) + } + } + + @Test + fun `getDirectRoomMember emit null if the room is not a dm`() = runTest { + val matrixRoom = FakeMatrixRoom( + sessionId = A_USER_ID, + isEncrypted = true, + isDirect = false, + ) + moleculeFlow(RecompositionMode.Immediate) { + matrixRoom.getDirectRoomMember( + MatrixRoomMembersState.Ready(persistentListOf(roomMember1, roomMember2)) + ) + }.test { + assertThat(awaitItem().value).isNull() + } + } + + @Test + fun `getDirectRoomMember emit null if the room is not encrypted`() = runTest { + val matrixRoom = FakeMatrixRoom( + sessionId = A_USER_ID, + isEncrypted = false, + isDirect = true, + ) + moleculeFlow(RecompositionMode.Immediate) { + matrixRoom.getDirectRoomMember( + MatrixRoomMembersState.Ready(persistentListOf(roomMember1, roomMember2)) + ) + }.test { + assertThat(awaitItem().value).isNull() + } + } + + @Test + fun `getDirectRoomMember emit null if the room has only 1 member`() = runTest { + val matrixRoom = FakeMatrixRoom( + sessionId = A_USER_ID, + isEncrypted = true, + isDirect = true, + ) + moleculeFlow(RecompositionMode.Immediate) { + matrixRoom.getDirectRoomMember( + MatrixRoomMembersState.Ready(persistentListOf(roomMember1)) + ) + }.test { + assertThat(awaitItem().value).isNull() + } + } + + @Test + fun `getDirectRoomMember emit null if the room has only 3 members`() = runTest { + val matrixRoom = FakeMatrixRoom( + sessionId = A_USER_ID, + isEncrypted = true, + isDirect = true, + ) + moleculeFlow(RecompositionMode.Immediate) { + matrixRoom.getDirectRoomMember( + MatrixRoomMembersState.Ready(persistentListOf(roomMember1, roomMember2, roomMember3)) + ) + }.test { + assertThat(awaitItem().value).isNull() + } + } + + @Test + fun `getDirectRoomMember emit null if the other member is not active`() = runTest { + val matrixRoom = FakeMatrixRoom( + sessionId = A_USER_ID, + isEncrypted = true, + isDirect = true, + ) + moleculeFlow(RecompositionMode.Immediate) { + matrixRoom.getDirectRoomMember( + MatrixRoomMembersState.Ready( + persistentListOf( + roomMember1, + roomMember2.copy(membership = RoomMembershipState.BAN), + ) + ) + ) + }.test { + assertThat(awaitItem().value).isNull() + } + } + + @Test + fun `getDirectRoomMember emit the other member if there are 2 active members`() = runTest { + val matrixRoom = FakeMatrixRoom( + sessionId = A_USER_ID, + isEncrypted = true, + isDirect = true, + ) + moleculeFlow(RecompositionMode.Immediate) { + matrixRoom.getDirectRoomMember( + MatrixRoomMembersState.Ready( + persistentListOf( + roomMember1, + roomMember2, + roomMember3.copy(membership = RoomMembershipState.BAN), + ) + ) + ) + }.test { + assertThat(awaitItem().value).isEqualTo(roomMember2) + } + } +} From 11691697d16fc03d226db6ff2a88557bbe52706d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Aug 2024 15:22:14 +0200 Subject: [PATCH 161/186] Add test on extension MatrixRoom.getCurrentRoomMember --- .../matrix/ui/room/MatrixRoomMembersTest.kt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembersTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembersTest.kt index 246f4f4fd5..1c3d6a82ad 100644 --- a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembersTest.kt +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembersTest.kt @@ -158,4 +158,39 @@ class MatrixRoomMembersTest { assertThat(awaitItem().value).isEqualTo(roomMember2) } } + + @Test + fun `getCurrentRoomMember returns the current user`() = runTest { + val matrixRoom = FakeMatrixRoom(sessionId = A_USER_ID) + moleculeFlow(RecompositionMode.Immediate) { + matrixRoom.getCurrentRoomMember( + MatrixRoomMembersState.Ready( + persistentListOf( + roomMember1, + roomMember2, + roomMember3, + ) + ) + ) + }.test { + assertThat(awaitItem().value).isEqualTo(roomMember1) + } + } + + @Test + fun `getCurrentRoomMember returns null if the member is not found`() = runTest { + val matrixRoom = FakeMatrixRoom(sessionId = A_USER_ID) + moleculeFlow(RecompositionMode.Immediate) { + matrixRoom.getCurrentRoomMember( + MatrixRoomMembersState.Ready( + persistentListOf( + roomMember2, + roomMember3, + ) + ) + ) + }.test { + assertThat(awaitItem().value).isNull() + } + } } From bb085251b24a03d697f2c57682afe48eab114ca7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Aug 2024 15:25:04 +0200 Subject: [PATCH 162/186] Reuse existing function --- .../android/libraries/matrix/ui/room/MatrixRoomMembers.kt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt index 2dbbe70f32..dfbaaeb2df 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt @@ -61,11 +61,5 @@ fun MatrixRoom.getDirectRoomMember(roomMembersState: MatrixRoomMembersState): St @Composable fun MatrixRoom.getCurrentRoomMember(roomMembersState: MatrixRoomMembersState): State { - val roomMembers = roomMembersState.roomMembers() - return remember(roomMembersState) { - derivedStateOf { - roomMembers - ?.find { it.userId == sessionId } - } - } + return getRoomMemberAsState(roomMembersState = roomMembersState, userId = sessionId) } From 785952628027668147a8fe18ec9121775379c784 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 22 Aug 2024 19:25:44 +0200 Subject: [PATCH 163/186] Improve the text for mentions and replies in notifications (#3328) --- .../DefaultNotifiableEventResolver.kt | 10 ++++------ .../factories/NotificationCreator.kt | 16 ++++++++++++++-- .../model/NotifiableMessageEvent.kt | 3 ++- .../DefaultNotifiableEventResolverTest.kt | 10 +++++++--- .../ui-strings/src/main/res/values/localazy.xml | 2 ++ 5 files changed, 29 insertions(+), 12 deletions(-) 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 1e186b38a8..953215feb2 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 @@ -104,11 +104,6 @@ class DefaultNotifiableEventResolver @Inject constructor( is NotificationContent.MessageLike.RoomMessage -> { val senderDisambiguatedDisplayName = getDisambiguatedDisplayName(content.senderId) val messageBody = descriptionFromMessageContent(content, senderDisambiguatedDisplayName) - val notificationBody = if (hasMention) { - stringProvider.getString(R.string.notification_mentioned_you_body, messageBody) - } else { - messageBody - } buildNotifiableMessageEvent( sessionId = userId, senderId = content.senderId, @@ -117,12 +112,13 @@ class DefaultNotifiableEventResolver @Inject constructor( noisy = isNoisy, timestamp = this.timestamp, senderDisambiguatedDisplayName = senderDisambiguatedDisplayName, - body = notificationBody, + body = messageBody, imageUriString = fetchImageIfPresent(client)?.toString(), roomName = roomDisplayName, roomIsDm = isDm, roomAvatarPath = roomAvatarUrl, senderAvatarPath = senderAvatarUrl, + hasMentionOrReply = hasMention, ) } is NotificationContent.StateEvent.RoomMemberContent -> { @@ -340,6 +336,7 @@ internal fun buildNotifiableMessageEvent( isRedacted: Boolean = false, isUpdated: Boolean = false, type: String = EventType.MESSAGE, + hasMentionOrReply: Boolean = false, ) = NotifiableMessageEvent( sessionId = sessionId, senderId = senderId, @@ -363,4 +360,5 @@ internal fun buildNotifiableMessageEvent( isRedacted = isRedacted, isUpdated = isUpdated, type = type, + hasMentionOrReply = hasMentionOrReply, ) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt index c7a5eb40d6..b1b4068efe 100755 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt @@ -397,10 +397,22 @@ class DefaultNotificationCreator @Inject constructor( val senderPerson = if (event.outGoingMessage) { null } else { + val senderName = event.senderDisambiguatedDisplayName.orEmpty() + // If the notification is for a mention or reply, we create a fake `Person` with a custom name and key + val displayName = if (event.hasMentionOrReply) { + stringProvider.getString(R.string.notification_sender_mention_reply, senderName) + } else { + senderName + } + val key = if (event.hasMentionOrReply) { + "mention-or-reply:${event.eventId.value}" + } else { + event.senderId.value + } Person.Builder() - .setName(event.senderDisambiguatedDisplayName?.annotateForDebug(70)) + .setName(displayName.annotateForDebug(70)) .setIcon(bitmapLoader.getUserIcon(event.senderAvatarPath, imageLoader)) - .setKey(event.senderId.value) + .setKey(key) .build() } when { diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt index b90af3df94..2862dda08b 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt @@ -52,7 +52,8 @@ data class NotifiableMessageEvent( val outGoingMessageFailed: Boolean = false, override val isRedacted: Boolean = false, override val isUpdated: Boolean = false, - val type: String = EventType.MESSAGE + val type: String = EventType.MESSAGE, + val hasMentionOrReply: Boolean = false, ) : NotifiableEvent { override val description: String = body ?: "" diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt index 1f6c98e914..0fa3f730aa 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt @@ -123,7 +123,7 @@ class DefaultNotifiableEventResolverTest { ) ) val result = sut.resolveEvent(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID) - val expectedResult = createNotifiableMessageEvent(body = "Mentioned you: Hello world") + val expectedResult = createNotifiableMessageEvent(body = "Hello world", hasMentionOrReply = true) assertThat(result).isEqualTo(expectedResult) } @@ -687,7 +687,10 @@ class DefaultNotifiableEventResolverTest { ) } - private fun createNotifiableMessageEvent(body: String): NotifiableMessageEvent { + private fun createNotifiableMessageEvent( + body: String, + hasMentionOrReply: Boolean = false, + ): NotifiableMessageEvent { return NotifiableMessageEvent( sessionId = A_SESSION_ID, roomId = A_ROOM_ID, @@ -708,7 +711,8 @@ class DefaultNotifiableEventResolverTest { outGoingMessage = false, outGoingMessageFailed = false, isRedacted = false, - isUpdated = false + isUpdated = false, + hasMentionOrReply = hasMentionOrReply, ) } } diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 730afa291e..501843bffb 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -112,6 +112,7 @@ "Tap for options" "Try again" "Unpin" + "View in timeline" "View source" "Yes" "About" @@ -177,6 +178,7 @@ Reason: %1$s." "People" "Permalink" "Permission" + "Pinned" "Please wait…" "Are you sure you want to end this poll?" "Poll: %1$s" From 5549c8fed34273d5d56c0437ca7d0f4dbf5ca79f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 04:45:32 +0000 Subject: [PATCH 164/186] Update dependency com.google.firebase:firebase-bom to v33.2.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 1d496a04af..7c5f5e440c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -67,7 +67,7 @@ kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", v kover_gradle_plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" } gms_google_services = "com.google.gms:google-services:4.4.2" # https://firebase.google.com/docs/android/setup#available-libraries -google_firebase_bom = "com.google.firebase:firebase-bom:33.1.2" +google_firebase_bom = "com.google.firebase:firebase-bom:33.2.0" firebase_appdistribution_gradle = { module = "com.google.firebase:firebase-appdistribution-gradle", version.ref = "firebaseAppDistribution" } autonomousapps_dependencyanalysis_plugin = { module = "com.autonomousapps:dependency-analysis-gradle-plugin", version.ref = "dependencyAnalysis" } oss_licenses_plugin = "com.google.android.gms:oss-licenses-plugin:0.10.6" From 18dcdc0e64d7c1d09c9edd1ab64a874a8208e052 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Aug 2024 16:17:57 +0200 Subject: [PATCH 165/186] Communicate with Element Call about PiP status. Also only use eventSink to communicate with the Presenter, instead of having public methods. Change WeakReference to an Activity to a listener and update tests. --- .../call/impl/pip/PictureInPictureEvents.kt | 4 + .../impl/pip/PictureInPicturePresenter.kt | 94 +++++++++--------- .../features/call/impl/pip/PipActivity.kt | 23 +++++ .../features/call/impl/ui/CallScreenView.kt | 3 + .../call/impl/ui/ElementCallActivity.kt | 51 +++++++++- .../features/call/impl/utils/WebPipApi.kt | 23 +++++ .../call/impl/utils/WebViewWebPipApi.kt | 41 ++++++++ .../features/call/impl/pip/FakePipActivity.kt | 29 ++++++ .../features/call/impl/pip/FakeWebPipApi.kt | 32 +++++++ .../impl/pip/PictureInPicturePresenterTest.kt | 96 ++++++++++++++----- 10 files changed, 317 insertions(+), 79 deletions(-) create mode 100644 features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipActivity.kt create mode 100644 features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebPipApi.kt create mode 100644 features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt create mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipActivity.kt create mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakeWebPipApi.kt diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt index da3c08da32..be376aa079 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt @@ -16,6 +16,10 @@ package io.element.android.features.call.impl.pip +import io.element.android.features.call.impl.utils.WebPipApi + sealed interface PictureInPictureEvents { + data class SetupWebPipApi(val webPipApi: WebPipApi) : PictureInPictureEvents data object EnterPictureInPicture : PictureInPictureEvents + data class OnPictureInPictureModeChanged(val isInPip: Boolean) : PictureInPictureEvents } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt index 2c974382d0..78d347d715 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt @@ -16,17 +16,17 @@ package io.element.android.features.call.impl.pip -import android.app.Activity -import android.app.PictureInPictureParams -import android.os.Build -import android.util.Rational -import androidx.annotation.RequiresApi import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import io.element.android.features.call.impl.utils.WebPipApi import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.log.logger.LoggerTag +import kotlinx.coroutines.launch import timber.log.Timber -import java.lang.ref.WeakReference import javax.inject.Inject private val loggerTag = LoggerTag("PiP") @@ -35,71 +35,69 @@ class PictureInPicturePresenter @Inject constructor( pipSupportProvider: PipSupportProvider, ) : Presenter { private val isPipSupported = pipSupportProvider.isPipSupported() - private var isInPictureInPicture = mutableStateOf(false) - private var hostActivity: WeakReference? = null + private var pipActivity: PipActivity? = null @Composable override fun present(): PictureInPictureState { + val coroutineScope = rememberCoroutineScope() + var isInPictureInPicture by remember { mutableStateOf(false) } + var webPipApi by remember { mutableStateOf(null) } + fun handleEvent(event: PictureInPictureEvents) { when (event) { - PictureInPictureEvents.EnterPictureInPicture -> switchToPip() + is PictureInPictureEvents.SetupWebPipApi -> { + webPipApi = event.webPipApi + } + PictureInPictureEvents.EnterPictureInPicture -> { + coroutineScope.launch { + switchToPip(webPipApi) + } + } + is PictureInPictureEvents.OnPictureInPictureModeChanged -> { + Timber.tag(loggerTag.value).d("onPictureInPictureModeChanged: ${event.isInPip}") + isInPictureInPicture = event.isInPip + if (event.isInPip) { + webPipApi?.enterPip() + } else { + webPipApi?.exitPip() + } + } } } return PictureInPictureState( supportPip = isPipSupported, - isInPictureInPicture = isInPictureInPicture.value, + isInPictureInPicture = isInPictureInPicture, eventSink = ::handleEvent, ) } - fun onCreate(activity: Activity) { + fun setPipActivity(pipActivity: PipActivity?) { if (isPipSupported) { - Timber.tag(loggerTag.value).d("onCreate: Setting PiP params") - hostActivity = WeakReference(activity) - hostActivity?.get()?.setPictureInPictureParams(getPictureInPictureParams()) + Timber.tag(loggerTag.value).d("Setting PiP params") + this.pipActivity = pipActivity + pipActivity?.setPipParams() } else { Timber.tag(loggerTag.value).d("onCreate: PiP is not supported") } } - fun onDestroy() { - Timber.tag(loggerTag.value).d("onDestroy") - hostActivity?.clear() - hostActivity = null - } - - @RequiresApi(Build.VERSION_CODES.O) - private fun getPictureInPictureParams(): PictureInPictureParams { - return PictureInPictureParams.Builder() - // Portrait for calls seems more appropriate - .setAspectRatio(Rational(3, 5)) - .apply { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - setAutoEnterEnabled(true) - } - } - .build() - } - /** - * Enters Picture-in-Picture mode. + * Enters Picture-in-Picture mode, if allowed by Element Call. */ - private fun switchToPip() { + private suspend fun switchToPip(webPipApi: WebPipApi?) { if (isPipSupported) { - Timber.tag(loggerTag.value).d("Switch to PiP mode") - hostActivity?.get()?.enterPictureInPictureMode(getPictureInPictureParams()) - ?.also { Timber.tag(loggerTag.value).d("Switch to PiP mode result: $it") } + if (webPipApi == null) { + Timber.tag(loggerTag.value).w("webPipApi is not available") + } + if (webPipApi == null || webPipApi.canEnterPip()) { + Timber.tag(loggerTag.value).d("Switch to PiP mode") + pipActivity?.enterPipMode() + ?.also { Timber.tag(loggerTag.value).d("Switch to PiP mode result: $it") } + } else { + Timber.tag(loggerTag.value).w("Cannot enter PiP mode, hangup the call") + pipActivity?.hangUp() + } } } - - fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) { - Timber.tag(loggerTag.value).d("onPictureInPictureModeChanged: $isInPictureInPictureMode") - isInPictureInPicture.value = isInPictureInPictureMode - } - - fun onUserLeaveHint() { - Timber.tag(loggerTag.value).d("onUserLeaveHint") - switchToPip() - } } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipActivity.kt new file mode 100644 index 0000000000..6b86988ae2 --- /dev/null +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipActivity.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call.impl.pip + +interface PipActivity { + fun setPipParams() + fun enterPipMode(): Boolean + fun hangUp() +} diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index 70ab2e30c2..e81d386dc5 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -40,6 +40,7 @@ import io.element.android.features.call.impl.pip.PictureInPictureEvents import io.element.android.features.call.impl.pip.PictureInPictureState import io.element.android.features.call.impl.pip.PictureInPictureStateProvider import io.element.android.features.call.impl.pip.aPictureInPictureState +import io.element.android.features.call.impl.utils.WebViewWebPipApi import io.element.android.features.call.impl.utils.WebViewWidgetMessageInterceptor import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.ProgressDialog @@ -108,6 +109,8 @@ internal fun CallScreenView( onWebViewCreate = { webView -> val interceptor = WebViewWidgetMessageInterceptor(webView) state.eventSink(CallScreenEvents.SetupMessageChannels(interceptor)) + val webPipApi = WebViewWebPipApi(webView) + pipState.eventSink(PictureInPictureEvents.SetupWebPipApi(webPipApi)) } ) when (state.urlState) { diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt index 3af6c7cf95..aace025bb4 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt @@ -17,6 +17,7 @@ package io.element.android.features.call.impl.ui import android.Manifest +import android.app.PictureInPictureParams import android.content.Intent import android.content.res.Configuration import android.media.AudioAttributes @@ -24,11 +25,13 @@ import android.media.AudioFocusRequest import android.media.AudioManager import android.os.Build import android.os.Bundle +import android.util.Rational import android.view.WindowManager import android.webkit.PermissionRequest import androidx.activity.compose.setContent import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts +import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.compose.runtime.mutableStateOf import androidx.core.content.IntentCompat @@ -36,7 +39,9 @@ import androidx.lifecycle.Lifecycle import io.element.android.features.call.api.CallType import io.element.android.features.call.impl.DefaultElementCallEntryPoint import io.element.android.features.call.impl.di.CallBindings +import io.element.android.features.call.impl.pip.PictureInPictureEvents import io.element.android.features.call.impl.pip.PictureInPicturePresenter +import io.element.android.features.call.impl.pip.PipActivity import io.element.android.features.call.impl.services.CallForegroundService import io.element.android.features.call.impl.utils.CallIntentDataParser import io.element.android.libraries.architecture.bindings @@ -45,7 +50,10 @@ import io.element.android.libraries.preferences.api.store.AppPreferencesStore import timber.log.Timber import javax.inject.Inject -class ElementCallActivity : AppCompatActivity(), CallScreenNavigator { +class ElementCallActivity : + AppCompatActivity(), + CallScreenNavigator, + PipActivity { @Inject lateinit var callIntentDataParser: CallIntentDataParser @Inject lateinit var presenterFactory: CallScreenPresenter.Factory @Inject lateinit var appPreferencesStore: AppPreferencesStore @@ -66,6 +74,7 @@ class ElementCallActivity : AppCompatActivity(), CallScreenNavigator { private val webViewTarget = mutableStateOf(null) private var eventSink: ((CallScreenEvents) -> Unit)? = null + private var pipEventSink: ((PictureInPictureEvents) -> Unit)? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -86,13 +95,14 @@ class ElementCallActivity : AppCompatActivity(), CallScreenNavigator { updateUiMode(resources.configuration) } - pictureInPicturePresenter.onCreate(this) + pictureInPicturePresenter.setPipActivity(this) audioManager = getSystemService(AUDIO_SERVICE) as AudioManager requestAudioFocus() setContent { val pipState = pictureInPicturePresenter.present() + pipEventSink = pipState.eventSink ElementThemeApp(appPreferencesStore) { val state = presenter.present() eventSink = state.eventSink @@ -115,7 +125,7 @@ class ElementCallActivity : AppCompatActivity(), CallScreenNavigator { override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) { super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig) - pictureInPicturePresenter.onPictureInPictureModeChanged(isInPictureInPictureMode) + pipEventSink?.invoke(PictureInPictureEvents.OnPictureInPictureModeChanged(isInPictureInPictureMode)) if (!isInPictureInPictureMode && !lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { Timber.d("Exiting PiP mode: Hangup the call") @@ -142,14 +152,14 @@ class ElementCallActivity : AppCompatActivity(), CallScreenNavigator { override fun onUserLeaveHint() { super.onUserLeaveHint() - pictureInPicturePresenter.onUserLeaveHint() + pipEventSink?.invoke(PictureInPictureEvents.EnterPictureInPicture) } override fun onDestroy() { super.onDestroy() releaseAudioFocus() CallForegroundService.stop(this) - pictureInPicturePresenter.onDestroy() + pictureInPicturePresenter.setPipActivity(null) } override fun finish() { @@ -249,6 +259,37 @@ class ElementCallActivity : AppCompatActivity(), CallScreenNavigator { } } } + + override fun setPipParams() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + setPictureInPictureParams(getPictureInPictureParams()) + } + } + + override fun enterPipMode(): Boolean { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + enterPictureInPictureMode(getPictureInPictureParams()) + } else { + false + } + } + + @RequiresApi(Build.VERSION_CODES.O) + private fun getPictureInPictureParams(): PictureInPictureParams { + return PictureInPictureParams.Builder() + // Portrait for calls seems more appropriate + .setAspectRatio(Rational(3, 5)) + .apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + setAutoEnterEnabled(true) + } + } + .build() + } + + override fun hangUp() { + eventSink?.invoke(CallScreenEvents.Hangup) + } } internal fun mapWebkitPermissions(permissions: Array): List { diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebPipApi.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebPipApi.kt new file mode 100644 index 0000000000..af1cc6b3f9 --- /dev/null +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebPipApi.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call.impl.utils + +interface WebPipApi { + suspend fun canEnterPip(): Boolean + fun enterPip() + fun exitPip() +} diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt new file mode 100644 index 0000000000..43b7dfadde --- /dev/null +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call.impl.utils + +import android.webkit.WebView +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine + +class WebViewWebPipApi( + private val webView: WebView, +) : WebPipApi { + override suspend fun canEnterPip(): Boolean { + return suspendCoroutine { continuation -> + webView.evaluateJavascript("controls.canEnterPip()") { result -> + continuation.resume(result == "true") + } + } + } + + override fun enterPip() { + webView.evaluateJavascript("controls.enablePip()", null) + } + + override fun exitPip() { + webView.evaluateJavascript("controls.disablePip()", null) + } +} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipActivity.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipActivity.kt new file mode 100644 index 0000000000..8a3089453e --- /dev/null +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipActivity.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call.impl.pip + +import io.element.android.tests.testutils.lambda.lambdaError + +class FakePipActivity( + private val setPipParamsResult: () -> Unit = { lambdaError() }, + private val enterPipModeResult: () -> Boolean = { lambdaError() }, + private val handUpResult: () -> Unit = { lambdaError() } +) : PipActivity { + override fun setPipParams() = setPipParamsResult() + override fun enterPipMode(): Boolean = enterPipModeResult() + override fun hangUp() = handUpResult() +} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakeWebPipApi.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakeWebPipApi.kt new file mode 100644 index 0000000000..ca752cd8ce --- /dev/null +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakeWebPipApi.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call.impl.pip + +import io.element.android.features.call.impl.utils.WebPipApi +import io.element.android.tests.testutils.lambda.lambdaError + +class FakeWebPipApi( + private val canEnterPipResult: () -> Boolean = { lambdaError() }, + private val enterPipResult: () -> Unit = { lambdaError() }, + private val exitPipResult: () -> Unit = { lambdaError() }, +) : WebPipApi { + override suspend fun canEnterPip(): Boolean = canEnterPipResult() + + override fun enterPip() = enterPipResult() + + override fun exitPip() = exitPipResult() +} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt index 895505c278..2343f2cb70 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt @@ -16,23 +16,16 @@ package io.element.android.features.call.impl.pip -import android.os.Build.VERSION_CODES import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.call.impl.ui.ElementCallActivity +import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.coroutines.test.runTest import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.Robolectric -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -@RunWith(RobolectricTestRunner::class) class PictureInPicturePresenterTest { @Test - @Config(sdk = [VERSION_CODES.O, VERSION_CODES.S]) fun `when pip is not supported, the state value supportPip is false`() = runTest { val presenter = createPictureInPicturePresenter(supportPip = false) moleculeFlow(RecompositionMode.Immediate) { @@ -41,68 +34,119 @@ class PictureInPicturePresenterTest { val initialState = awaitItem() assertThat(initialState.supportPip).isFalse() } - presenter.onDestroy() + presenter.setPipActivity(null) } @Test - @Config(sdk = [VERSION_CODES.O, VERSION_CODES.S]) fun `when pip is supported, the state value supportPip is true`() = runTest { - val presenter = createPictureInPicturePresenter(supportPip = true) + val presenter = createPictureInPicturePresenter( + supportPip = true, + pipActivity = FakePipActivity(setPipParamsResult = { }), + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() assertThat(initialState.supportPip).isTrue() } - presenter.onDestroy() } @Test - @Config(sdk = [VERSION_CODES.S]) fun `when entering pip is supported, the state value isInPictureInPicture is true`() = runTest { - val presenter = createPictureInPicturePresenter(supportPip = true) + val enterPipModeResult = lambdaRecorder { true } + val presenter = createPictureInPicturePresenter( + supportPip = true, + pipActivity = FakePipActivity( + setPipParamsResult = { }, + enterPipModeResult = enterPipModeResult, + ), + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() assertThat(initialState.isInPictureInPicture).isFalse() initialState.eventSink(PictureInPictureEvents.EnterPictureInPicture) - presenter.onPictureInPictureModeChanged(true) + enterPipModeResult.assertions().isCalledOnce() + initialState.eventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(true)) val pipState = awaitItem() assertThat(pipState.isInPictureInPicture).isTrue() // User stops pip - presenter.onPictureInPictureModeChanged(false) + initialState.eventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(false)) val finalState = awaitItem() assertThat(finalState.isInPictureInPicture).isFalse() } - presenter.onDestroy() } @Test - @Config(sdk = [VERSION_CODES.S]) - fun `when onUserLeaveHint is called, the state value isInPictureInPicture becomes true`() = runTest { - val presenter = createPictureInPicturePresenter(supportPip = true) + fun `with webPipApi, when entering pip is supported, but web deny it, the call is finished`() = runTest { + val handUpResult = lambdaRecorder { } + val presenter = createPictureInPicturePresenter( + supportPip = true, + pipActivity = FakePipActivity( + setPipParamsResult = { }, + handUpResult = handUpResult + ), + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - assertThat(initialState.isInPictureInPicture).isFalse() - presenter.onUserLeaveHint() - presenter.onPictureInPictureModeChanged(true) + initialState.eventSink(PictureInPictureEvents.SetupWebPipApi(FakeWebPipApi(canEnterPipResult = { false }))) + initialState.eventSink(PictureInPictureEvents.EnterPictureInPicture) + handUpResult.assertions().isCalledOnce() + } + } + + @Test + fun `with webPipApi, when entering pip is supported, and web allows it, the state value isInPictureInPicture is true`() = runTest { + val enterPipModeResult = lambdaRecorder { true } + val enterPipResult = lambdaRecorder { } + val exitPipResult = lambdaRecorder { } + val presenter = createPictureInPicturePresenter( + supportPip = true, + pipActivity = FakePipActivity( + setPipParamsResult = { }, + enterPipModeResult = enterPipModeResult + ), + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink( + PictureInPictureEvents.SetupWebPipApi( + FakeWebPipApi( + canEnterPipResult = { true }, + enterPipResult = enterPipResult, + exitPipResult = exitPipResult, + ) + ) + ) + initialState.eventSink(PictureInPictureEvents.EnterPictureInPicture) + enterPipModeResult.assertions().isCalledOnce() + enterPipResult.assertions().isNeverCalled() + initialState.eventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(true)) val pipState = awaitItem() assertThat(pipState.isInPictureInPicture).isTrue() + enterPipResult.assertions().isCalledOnce() + // User stops pip + exitPipResult.assertions().isNeverCalled() + initialState.eventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(false)) + val finalState = awaitItem() + assertThat(finalState.isInPictureInPicture).isFalse() + exitPipResult.assertions().isCalledOnce() } - presenter.onDestroy() } private fun createPictureInPicturePresenter( supportPip: Boolean = true, + pipActivity: PipActivity? = FakePipActivity() ): PictureInPicturePresenter { - val activity = Robolectric.buildActivity(ElementCallActivity::class.java) return PictureInPicturePresenter( pipSupportProvider = FakePipSupportProvider(supportPip), ).apply { - onCreate(activity.get()) + setPipActivity(pipActivity) } } } From 368db3feb48c5a2b5c9aca9aa5b1ffadc2b25154 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Aug 2024 16:28:13 +0200 Subject: [PATCH 166/186] Allow entering Pip mode when `controls.canEnterPip()` cannot be evaluated. --- .../android/features/call/impl/utils/WebViewWebPipApi.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt index 43b7dfadde..baf682d6b3 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt @@ -26,7 +26,8 @@ class WebViewWebPipApi( override suspend fun canEnterPip(): Boolean { return suspendCoroutine { continuation -> webView.evaluateJavascript("controls.canEnterPip()") { result -> - continuation.resume(result == "true") + // Note if the method is not available, it will return "null" + continuation.resume(result == "true" || result == "null") } } } From a4b6d4c5d77b570dae4dc4f5df721527a54a7716 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Aug 2024 16:34:44 +0200 Subject: [PATCH 167/186] Simplify code. --- .../features/call/impl/ui/ElementCallActivity.kt | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt index aace025bb4..8c758c2ee5 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt @@ -260,18 +260,14 @@ class ElementCallActivity : } } + @RequiresApi(Build.VERSION_CODES.O) override fun setPipParams() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - setPictureInPictureParams(getPictureInPictureParams()) - } + setPictureInPictureParams(getPictureInPictureParams()) } + @RequiresApi(Build.VERSION_CODES.O) override fun enterPipMode(): Boolean { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - enterPictureInPictureMode(getPictureInPictureParams()) - } else { - false - } + return enterPictureInPictureMode(getPictureInPictureParams()) } @RequiresApi(Build.VERSION_CODES.O) From 0b2edcb6d14fe3dd5d0b2c41cb8af3ea9d987f2b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Aug 2024 16:40:48 +0200 Subject: [PATCH 168/186] Fix UI tests. --- .../android/features/call/impl/ui/CallScreenViewTest.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/ui/CallScreenViewTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/ui/CallScreenViewTest.kt index 6d15e5001c..e92e9cc4e6 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/ui/CallScreenViewTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/ui/CallScreenViewTest.kt @@ -37,7 +37,7 @@ class CallScreenViewTest { @Test fun `clicking on back when pip is not supported hangs up`() { val eventsRecorder = EventsRecorder() - val pipEventsRecorder = EventsRecorder(expectEvents = false) + val pipEventsRecorder = EventsRecorder() rule.setCallScreenView( aCallScreenState( eventSink = eventsRecorder @@ -51,6 +51,8 @@ class CallScreenViewTest { eventsRecorder.assertSize(2) eventsRecorder.assertTrue(0) { it is CallScreenEvents.SetupMessageChannels } eventsRecorder.assertTrue(1) { it == CallScreenEvents.Hangup } + pipEventsRecorder.assertSize(1) + pipEventsRecorder.assertTrue(0) { it is PictureInPictureEvents.SetupWebPipApi } } @Test @@ -69,7 +71,9 @@ class CallScreenViewTest { rule.pressBack() eventsRecorder.assertSize(1) eventsRecorder.assertTrue(0) { it is CallScreenEvents.SetupMessageChannels } - pipEventsRecorder.assertSingle(PictureInPictureEvents.EnterPictureInPicture) + pipEventsRecorder.assertSize(2) + pipEventsRecorder.assertTrue(0) { it is PictureInPictureEvents.SetupWebPipApi } + pipEventsRecorder.assertTrue(1) { it == PictureInPictureEvents.EnterPictureInPicture } } } From 107b29545dfcf94d5186b825407efe54a2d8613f Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Sat, 24 Aug 2024 22:18:57 +0200 Subject: [PATCH 169/186] Fix login navigation getting stuck with no-op analytics provider Change-Id: Icac04e1193e12943c2b8598f48d79ac6e7cef3a5 --- .../android/features/ftue/impl/state/DefaultFtueService.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/DefaultFtueService.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/DefaultFtueService.kt index 24c9c7df82..6d22bb7b2c 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/DefaultFtueService.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/DefaultFtueService.kt @@ -98,7 +98,10 @@ class DefaultFtueService @Inject constructor( } else { getNextStep(FtueStep.AnalyticsOptIn) } - FtueStep.AnalyticsOptIn -> null + FtueStep.AnalyticsOptIn -> { + updateState() + null + } } private suspend fun isAnyStepIncomplete(): Boolean { From cd267249ec0398d4f760f2d4fa093b2675a35c14 Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 26 Aug 2024 00:25:40 +0000 Subject: [PATCH 170/186] Sync Strings from Localazy --- .../src/main/res/values-nl/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 33 + .../src/main/res/values-nl/translations.xml | 2 + .../src/main/res/values-nl/translations.xml | 10 + .../src/main/res/values-nl/translations.xml | 11 + .../src/main/res/values-nl/translations.xml | 8 + .../src/main/res/values-nl/translations.xml | 11 + .../src/main/res/values-nl/translations.xml | 2 + .../src/main/res/values-nl/translations.xml | 19 + .../src/main/res/values-nl/translations.xml | 8 + .../src/main/res/values-fr/translations.xml | 1 + .../src/main/res/values-hu/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 35 +- .../impl/src/main/res/values/localazy.xml | 4 +- .../src/main/res/values-nl/translations.xml | 4 + .../src/main/res/values-nl/translations.xml | 3 + .../src/main/res/values-cs/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 1 + .../src/main/res/values-hu/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 2 + .../src/main/res/values-sk/translations.xml | 1 + .../src/main/res/values-be/translations.xml | 2 + .../src/main/res/values-cs/translations.xml | 5 + .../src/main/res/values-de/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 5 + .../src/main/res/values-fr/translations.xml | 2 + .../src/main/res/values-hu/translations.xml | 12 + .../src/main/res/values-nl/translations.xml | 43 +- .../src/main/res/values-ru/translations.xml | 2 + .../src/main/res/values-sk/translations.xml | 5 + .../src/main/res/values-sv/translations.xml | 2 + .../src/main/res/values/localazy.xml | 3 + ..._MentionSuggestionsPickerView_Day_0_de.png | 3 - ...estions_SuggestionsPickerView_Day_0_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_2_de.png | 4 +- ...nner_PinnedMessagesBannerView_Day_4_de.png | 4 +- ...nner_PinnedMessagesBannerView_Day_5_de.png | 4 +- ...nner_PinnedMessagesBannerView_Day_6_de.png | 4 +- ...nner_PinnedMessagesBannerView_Day_7_de.png | 4 +- ...nner_PinnedMessagesBannerView_Day_8_de.png | 4 +- ...nner_PinnedMessagesBannerView_Day_9_de.png | 4 +- ...s.messages.impl_MessagesView_Day_13_de.png | 4 +- ...ord_ResetIdentityPasswordView_Day_0_de.png | 4 +- ...ord_ResetIdentityPasswordView_Day_1_de.png | 4 +- ...ord_ResetIdentityPasswordView_Day_2_de.png | 4 +- ...ord_ResetIdentityPasswordView_Day_3_de.png | 4 +- ...et.root_ResetIdentityRootView_Day_1_de.png | 4 +- screenshots/html/data.js | 1164 ++++++++--------- ...ord_ResetIdentityPasswordView_Day_0_en.png | 4 +- ...ord_ResetIdentityPasswordView_Day_1_en.png | 4 +- ...ord_ResetIdentityPasswordView_Day_2_en.png | 4 +- ...ord_ResetIdentityPasswordView_Day_3_en.png | 4 +- ...d_ResetIdentityPasswordView_Night_0_en.png | 4 +- ...d_ResetIdentityPasswordView_Night_1_en.png | 4 +- ...d_ResetIdentityPasswordView_Night_2_en.png | 4 +- ...d_ResetIdentityPasswordView_Night_3_en.png | 4 +- ...et.root_ResetIdentityRootView_Day_1_en.png | 4 +- ....root_ResetIdentityRootView_Night_1_en.png | 4 +- 58 files changed, 867 insertions(+), 637 deletions(-) delete mode 100644 screenshots/de/features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_de.png create mode 100644 screenshots/de/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_de.png diff --git a/features/leaveroom/api/src/main/res/values-nl/translations.xml b/features/leaveroom/api/src/main/res/values-nl/translations.xml index 4051ff5274..bef0aff089 100644 --- a/features/leaveroom/api/src/main/res/values-nl/translations.xml +++ b/features/leaveroom/api/src/main/res/values-nl/translations.xml @@ -1,5 +1,6 @@ + "Weet je zeker dat je dit gesprek wilt verlaten? Dit gesprek is niet openbaar en je kunt niet opnieuw deelnemen zonder een uitnodiging." "Weet je zeker dat je deze kamer wilt verlaten? Je bent de enige persoon hier. Als je weggaat, kan er in de toekomst niemand meer toetreden, ook jij niet." "Weet je zeker dat je deze kamer wilt verlaten? Deze kamer is niet openbaar en je kunt niet opnieuw deelnemen zonder een uitnodiging." "Weet je zeker dat je de kamer wilt verlaten?" diff --git a/features/lockscreen/impl/src/main/res/values-nl/translations.xml b/features/lockscreen/impl/src/main/res/values-nl/translations.xml index 1353f35a74..419d6d5518 100644 --- a/features/lockscreen/impl/src/main/res/values-nl/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-nl/translations.xml @@ -1,4 +1,37 @@ + "biometrische authenticatie" + "biometrische ontgrendeling" + "Ontgrendelen met biometrie" + "Pincode vergeten?" + "Pincode wijzigen" + "Biometrische ontgrendeling toestaan" + "Pincode verwijderen" + "Weet je zeker dat je de pincode wilt verwijderen?" + "Pincode verwijderen?" + "%1$s toestaan" + "Ik gebruik liever een pincode" + "Bespaar jezelf tijd en gebruik %1$s om de app elke keer te ontgrendelen" + "Kies je pincode" + "Bevestig pincode" + "Vergrendel %1$s om je chats extra te beveiligen. + +Kies iets dat je kunt onthouden. Als je deze pincode vergeet, word je uitgelogd bij de app." + "Vanwege veiligheidsredenen kun je dit niet als je pincode kiezen" + "Kies een andere pincode" + "Voer dezelfde pincode twee keer in" + "Pincodes komen niet overeen" + "Je moet opnieuw inloggen en een nieuwe pincode aanmaken om verder te gaan" + "Je wordt uitgelogd" + + "Je hebt %1$d poging om te ontgrendelen" + "Je hebt %1$d pogingen om te ontgrendelen" + + + "Verkeerde pincode. Je hebt nog %1$d kans" + "Verkeerde pincode. Je hebt nog %1$d kansen" + + "Biometrie gebruiken" + "Pincode gebruiken" "Uitloggen…" diff --git a/features/login/impl/src/main/res/values-nl/translations.xml b/features/login/impl/src/main/res/values-nl/translations.xml index 7df748da03..80fbe57afb 100644 --- a/features/login/impl/src/main/res/values-nl/translations.xml +++ b/features/login/impl/src/main/res/values-nl/translations.xml @@ -22,11 +22,13 @@ "Dit account is gedeactiveerd." "Onjuiste gebruikersnaam en/of wachtwoord" "Dit is geen geldige gebruikers-ID. Verwacht formaat: \'@user:homeserver.org\'" + "Deze server is geconfigureerd om verversingstokens te gebruiken. Deze worden niet ondersteund bij inloggen met een wachtwoord." "De geselecteerde homeserver ondersteunt geen wachtwoord of OIDC aanmelding. Neem contact op met je beheerder of kies een andere homeserver." "Vul je gegevens in" "Matrix is een open netwerk voor veilige, gedecentraliseerde communicatie." "Welkom terug!" "Inloggen bij %1$s" + "Probeer het opnieuw" "Accountprovider wijzigen" "Een privéserver voor medewerkers van Element." "Matrix is een open netwerk voor veilige, gedecentraliseerde communicatie." diff --git a/features/logout/impl/src/main/res/values-nl/translations.xml b/features/logout/impl/src/main/res/values-nl/translations.xml index 8d7c10d17d..174102a0a2 100644 --- a/features/logout/impl/src/main/res/values-nl/translations.xml +++ b/features/logout/impl/src/main/res/values-nl/translations.xml @@ -4,5 +4,15 @@ "Uitloggen" "Uitloggen" "Uitloggen…" + "Je staat op het punt uit te loggen bij je laatste sessie. Als je je nu uitlogt, verlies je de toegang tot je versleutelde berichten." + "Je hebt de back-up uitgeschakeld" + "De backup van je sleutels was nog bezig toen je offline ging. Maak opnieuw verbinding zodat er een back-up van je sleutels kan worden gemaakt voordat je uitlogt." + "De backup van je sleutels is nog bezig" + "Wacht tot dit voltooid is voordat je uitlogt." + "De backup van je sleutels is nog bezig" "Uitloggen" + "Je staat op het punt uit te loggen bij je laatste sessie. Als je je nu uitlogt, verlies je de toegang tot je versleutelde berichten." + "Herstelmogelijkheid niet ingesteld" + "Je staat op het punt uit te loggen bij je laatste sessie. Als je je nu uitlogt, kan het dat je de toegang tot je versleutelde berichten verliest." + "Heb je je herstelsleutel opgeslagen?" diff --git a/features/messages/impl/src/main/res/values-nl/translations.xml b/features/messages/impl/src/main/res/values-nl/translations.xml index 87bbe0e7a7..e7464c63bd 100644 --- a/features/messages/impl/src/main/res/values-nl/translations.xml +++ b/features/messages/impl/src/main/res/values-nl/translations.xml @@ -21,8 +21,10 @@ "Peiling" "Tekstopmaak" "Berichtgeschiedenis is momenteel niet beschikbaar." + "Berichtgeschiedenis is niet beschikbaar in deze kamer. Verifieer dit apparaat om je berichtgeschiedenis te bekijken." "Wil je ze terug uitnodigen?" "Je bent alleen in deze chat" + "Stuur een melding naar de hele kamer" "Iedereen" "Opnieuw verzenden" "Je bericht is niet verzonden" @@ -39,4 +41,13 @@ "%1$d kamerverandering" "%1$d kamerveranderingen" + + "%1$s, %2$s en %3$d andere" + "%1$s, %2$s en %3$d anderen" + + + "%1$s is aan het typen" + "%1$s zijn aan het typen" + + "%1$s en %2$s" diff --git a/features/poll/impl/src/main/res/values-nl/translations.xml b/features/poll/impl/src/main/res/values-nl/translations.xml index b3c0ae1f78..e6c99c1201 100644 --- a/features/poll/impl/src/main/res/values-nl/translations.xml +++ b/features/poll/impl/src/main/res/values-nl/translations.xml @@ -4,8 +4,16 @@ "Resultaten pas weergeven nadat de peiling is afgelopen" "Stemmen verbergen" "Optie %1$d" + "Je wijzigingen zijn niet opgeslagen. Weet je zeker dat je terug wilt gaan?" "Vraag of onderwerp" "Waar gaat de peiling over?" "Peiling maken" + "Weet je zeker dat je deze peiling wilt verwijderen?" + "Peiling verwijderen" "Peiling wijzigen" + "Kan geen actieve peilingen vinden." + "Kan geen eerdere peilingen vinden." + "Actief" + "Afgelopen" + "Peilingen" diff --git a/features/preferences/impl/src/main/res/values-nl/translations.xml b/features/preferences/impl/src/main/res/values-nl/translations.xml index 2e4497718d..6296b409b2 100644 --- a/features/preferences/impl/src/main/res/values-nl/translations.xml +++ b/features/preferences/impl/src/main/res/values-nl/translations.xml @@ -3,10 +3,19 @@ "Kies hoe je meldingen wilt ontvangen" "Ontwikkelaarsmodus" "Schakel in om toegang te krijgen tot tools en functies voor ontwikkelaars." + "Aangepaste basis-URL voor Element Call" + "Stel een aangepaste basis-URL in voor Element Call." + "Ongeldige URL, zorg ervoor dat je het protocol (http/https) en het juiste adres invult." "Schakel de uitgebreide tekstverwerker uit om Markdown handmatig te typen." + "Leesbevestigingen" + "Indien uitgeschakeld worden er geen leesbevestigingen verstuurd. Je ontvangt nog steeds leesbevestigingen van andere gebruikers." + "Aanwezigheid delen" + "Indien uitgeschakeld kun je geen leesbevestigingen en typmeldingen verzenden of ontvangen." + "Schakel optie in om de berichtbron in de tijdlijn te bekijken." "Deblokkeren" "Je zult alle berichten van hen weer kunnen zien." "Gebruiker deblokkeren" + "Deblokkeren…" "Weergavenaam" "Je weergavenaam" "Er is een onbekende fout opgetreden en de informatie kon niet worden gewijzigd." @@ -29,6 +38,8 @@ Als je doorgaat, kunnen sommige van je instellingen veranderen." "Meldingen op dit apparaat inschakelen" "De configuratie is niet gecorrigeerd. Probeer het opnieuw." "Groep chats" + "Uitnodigingen" + "Je homeserver ondersteunt deze optie niet in versleutelde kamers; in sommige kamers krijg je mogelijk geen meldingen." "Vermeldingen" "Alles" "Vermeldingen" diff --git a/features/rageshake/impl/src/main/res/values-nl/translations.xml b/features/rageshake/impl/src/main/res/values-nl/translations.xml index 771c95fc6e..dbf62aade8 100644 --- a/features/rageshake/impl/src/main/res/values-nl/translations.xml +++ b/features/rageshake/impl/src/main/res/values-nl/translations.xml @@ -7,9 +7,11 @@ "Beschrijf het probleem. Wat heb je gedaan? Wat had je verwacht? Wat is er daadwerkelijk gebeurd. Beschrijf het zo gedetailleerd mogelijk." "Beschrijf het probleem…" "Geeft de beschrijving in het Engels indien mogelijk." + "De beschrijving is te kort, geef meer details over wat er is gebeurd. Bedankt!" "Crashlogboeken verzenden" "Logboeken toestaan" "Schermafbeelding verzenden" "Er worden logbestanden bij uw bericht gevoegd om er zeker van te zijn dat alles goed werkt. Als u uw bericht zonder logbestanden wilt verzenden, schakelt u deze instelling uit." "%1$s crashte de laatste keer dat het werd gebruikt. Wil je een crashrapport met ons delen?" + "Logboeken weergeven" diff --git a/features/roomdetails/impl/src/main/res/values-nl/translations.xml b/features/roomdetails/impl/src/main/res/values-nl/translations.xml index f3b274ae0c..117ef56b9f 100644 --- a/features/roomdetails/impl/src/main/res/values-nl/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-nl/translations.xml @@ -1,7 +1,13 @@ "Er is een fout opgetreden bij het bijwerken van de meldingsinstelling." + "Je homeserver ondersteunt deze optie niet in versleutelde kamers; in sommige kamers krijg je mogelijk geen meldingen." + "Peilingen" "Iedereen" + "Je kunt deze actie niet ongedaan maken. Je bevordert deze gebruiker tot hetzelfde machtsniveau als jij." + "Beheerder toevoegen?" + "Jezelf degraderen?" + "Leden" "Onderwerp toevoegen" "Reeds lid" "Reeds uitgenodigd" @@ -14,6 +20,7 @@ "Het dempen van deze kamer is mislukt. Probeer het opnieuw." "Het dempen opheffen voor deze kamer is mislukt. Probeer het opnieuw." "Mensen uitnodigen" + "Gesprek verlaten" "Ruimte verlaten" "Aangepast" "Standaard" @@ -27,7 +34,18 @@ "%1$d persoon" "%1$d personen" + "Verwijderen uit kamer" + "Lid verwijderen en verbannen" + "Alleen lid verwijderen" + "Lid verwijderen en toekomstige deelname verbieden?" + "Ontbannen" + "Profiel bekijken" + "Verbannen" + "Leden" "In behandeling" + "%1$s wordt verwijderd…" + "Beheerder" + "Moderator" "Kamerleden" "Aanpassen toestaan" "Als je dit inschakelt, wordt je standaardinstelling overschreven" @@ -39,6 +57,7 @@ "Er is een fout opgetreden bij het laden van de meldingsinstellingen." "Het herstellen van de standaardmeldingen is mislukt. Probeer het opnieuw." "Het instellen van de meldingen is mislukt. Probeer het opnieuw." + "Je homeserver ondersteunt deze optie niet in versleutelde kamers; in deze kamer krijg je geen meldingen." "Alle berichten" "Alleen vermeldingen en trefwoorden" "In deze kamer, stuur me een melding voor" diff --git a/features/roomlist/impl/src/main/res/values-nl/translations.xml b/features/roomlist/impl/src/main/res/values-nl/translations.xml index df2a4ce410..a20e0a695c 100644 --- a/features/roomlist/impl/src/main/res/values-nl/translations.xml +++ b/features/roomlist/impl/src/main/res/values-nl/translations.xml @@ -1,5 +1,7 @@ + "Je chatback-up is momenteel niet gesynchroniseerd. Je moet je herstelsleutel invoeren om toegang te behouden tot je chatback-up." + "Voer je herstelsleutel in" "Weet je zeker dat je de uitnodiging om toe te treden tot %1$s wilt weigeren?" "Uitnodiging weigeren" "Weet je zeker dat je deze privéchat met %1$s wilt weigeren?" @@ -11,8 +13,14 @@ "Begin een nieuw gesprek of maak een nieuwe kamer" "Ga aan de slag door iemand een bericht te sturen." "Nog geen chats." + "Favorieten" + "Lage prioriteit" "Personen" + "Kamers" + "Ongelezen" "Chats" + "Markeren als gelezen" + "Markeren als ongelezen" "Het lijkt erop dat je een nieuw apparaat gebruikt. Verifieer met een ander apparaat om toegang te krijgen tot je versleutelde berichten." "Verifieer dat jij het bent" diff --git a/features/securebackup/impl/src/main/res/values-fr/translations.xml b/features/securebackup/impl/src/main/res/values-fr/translations.xml index 68d6ac2e19..b0eb80b541 100644 --- a/features/securebackup/impl/src/main/res/values-fr/translations.xml +++ b/features/securebackup/impl/src/main/res/values-fr/translations.xml @@ -56,6 +56,7 @@ "Configurer la sauvegarde" "Oui, réinitialisez maintenant" "Cette opération ne peut pas être annulée." + "Une erreur s’est produite. Vérifiez que le mot de passe de votre compte est correct et réessayez." "Saisissez…" "Saisissez le mot de passe de votre compte pour continuer" diff --git a/features/securebackup/impl/src/main/res/values-hu/translations.xml b/features/securebackup/impl/src/main/res/values-hu/translations.xml index 6def2d41cd..312ad0705c 100644 --- a/features/securebackup/impl/src/main/res/values-hu/translations.xml +++ b/features/securebackup/impl/src/main/res/values-hu/translations.xml @@ -60,6 +60,7 @@ "Igen, visszaállítás most" "Ez a folyamat visszafordíthatatlan." "Biztos, hogy visszaállítja a titkosítást?" + "Ismeretlen hiba történt. Ellenőrizze, hogy a fiókja jelszava helyes-e, és próbálja meg újra." "Adja meg…" "Erősítse meg, hogy vissza szeretné állítani a titkosítást." "A folytatáshoz adja meg fiókja jelszavát" diff --git a/features/securebackup/impl/src/main/res/values-nl/translations.xml b/features/securebackup/impl/src/main/res/values-nl/translations.xml index 80460745ca..b4dbb23562 100644 --- a/features/securebackup/impl/src/main/res/values-nl/translations.xml +++ b/features/securebackup/impl/src/main/res/values-nl/translations.xml @@ -4,10 +4,41 @@ "Back-up inschakelen" "Een back-up maken zorgt ervoor dat je je berichtgeschiedenis niet verliest. %1$s." "Back-up" - "Wijzig recovery key" - "Voer recovery key in" + "Herstelsleutel wijzigen" + "Voer herstelsleutel in" "Je chatback-up is momenteel niet gesynchroniseerd." "Herstelmogelijkheid instellen" "Krijg toegang tot je versleutelde berichten als je al je apparaten kwijtraakt of overal uit %1$s bent uitgelogd." + "Uitschakelen" + "Je verliest je versleutelde berichten als je bent uitgelogd op alle apparaten." + "Weet je zeker dat je de back-up wilt uitschakelen?" + "Als je de back-up uitschakelt, verwijder je de back-up van je huidige versleuteling en schakel je andere beveiligingsfuncties uit. In dit geval zul je:" + "Geen berichtgeschiedenis hebben van versleutelde berichten op nieuwe apparaten" + "Toegang verliezen tot je versleutelde berichten als je overal uit %1$s bent uitgelogd." "Weet je zeker dat je de back-up wilt uitschakelen?" + "Maak een nieuwe herstelsleutel aan als je je bestaande kwijt bent. Nadat je je herstelsleutel hebt gewijzigd, werkt je oude herstelsleutel niet meer." + "Genereer een nieuwe herstelsleutel" + "Zorg ervoor dat je je herstelsleutel op een veilige plek kunt bewaren" + "Herstelsleutel gewijzigd" + "Herstelsleutel wijzigen?" + "Zorg ervoor dat niemand dit scherm kan zien!" + "Probeer het opnieuw om toegang tot je chatback-up te bevestigen." + "Onjuiste herstelsleutel" + "Als je een beveiligingssleutel of beveiligingszin hebt, werkt dit ook." + "Voer in…" + "Herstelsleutel bevestigd" + "Voer je herstelsleutel in" + "Herstelsleutel gekopieerd" + "Genereren…" + "Herstelsleutel opslaan" + "Noteer je herstelsleutel op een veilige plek of bewaar deze in een wachtwoordmanager." + "Tik om de herstelsleutel te kopiëren" + "Sla je herstelsleutel op" + "Na deze stap kun je je nieuwe herstelsleutel niet meer inzien." + "Heb je je herstelsleutel opgeslagen?" + "Je chatback-up wordt beschermd door een herstelsleutel. Als je na de installatie een nieuwe herstelsleutel nodig hebt, kun je deze opnieuw aanmaken door \'Herstelsleutel wijzigen\' te selecteren." + "Genereer je herstelsleutel" + "Zorg ervoor dat je je herstelsleutel op een veilige plek kunt bewaren" + "Herstelmogelijkheid succesvol ingesteld" + "Herstelmogelijkheid instellen" diff --git a/features/securebackup/impl/src/main/res/values/localazy.xml b/features/securebackup/impl/src/main/res/values/localazy.xml index 85e801fce1..6c428d4039 100644 --- a/features/securebackup/impl/src/main/res/values/localazy.xml +++ b/features/securebackup/impl/src/main/res/values/localazy.xml @@ -59,9 +59,9 @@ "Set up recovery" "Yes, reset now" "This process is irreversible." - "Are you sure you want to reset your encryption?" + "Are you sure you want to reset your identity?" "An unknown error happened. Please check your account password is correct and try again." "Enter…" - "Confirm that you want to reset your encryption." + "Confirm that you want to reset your identity." "Enter your account password to continue" diff --git a/features/verifysession/impl/src/main/res/values-nl/translations.xml b/features/verifysession/impl/src/main/res/values-nl/translations.xml index 39744242c5..b04e03307d 100644 --- a/features/verifysession/impl/src/main/res/values-nl/translations.xml +++ b/features/verifysession/impl/src/main/res/values-nl/translations.xml @@ -3,12 +3,16 @@ "Er lijkt iets niet goed te gaan. Of er is een time-out opgetreden of het verzoek is geweigerd." "Bevestig dat de emoji\'s hieronder overeenkomen met de emoji\'s in je andere sessie." "Vergelijk emoji\'s" + "Bevestig dat de onderstaande cijfers overeenkomen met de cijfers die worden weergegeven in je andere sessie." + "Vergelijk getallen" "Je nieuwe sessie is nu geverifieerd. Het heeft toegang tot je versleutelde berichten en andere gebruikers zullen het als vertrouwd beschouwen." + "Voer recovery key in" "Bewijs dat jij het bent om toegang te krijgen tot je versleutelde berichtgeschiedenis." "Open een bestaande sessie" "Verificatie opnieuw proberen" "Ik ben er klaar voor" "Wachten om te vergelijken" + "Vergelijk een unieke combinatie van emoji\'s." "Vergelijk de unieke emoji\'s, ze dienen in dezelfde volgorde te worden weergegeven." "Ze komen niet overeen" "Ze komen overeen" diff --git a/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml b/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml index a29c433f66..b10c806572 100644 --- a/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml @@ -1,6 +1,7 @@ "(afbeelding is ook gewijzigd)" + "%1$s wijzigde van afbeelding" "Je hebt je afbeelding gewijzigd" "%1$s heeft de weergavenaam aangepast van %2$s naar %3$s" "Je hebt je weergavenaam aangepast van %1$s naar %2$s" @@ -38,6 +39,8 @@ "Je hebt de kamernaam gewijzigd naar: %1$s" "%1$s heeft de kamernaam verwijderd" "Je hebt de kamernaam verwijderd" + "%1$s heeft geen wijzigingen aangebracht" + "Je hebt geen wijzigingen aangebracht" "%1$s heeft de uitnodiging afgewezen" "Je hebt de uitnodiging afgewezen" "%1$s heeft %2$s verwijderd" diff --git a/libraries/push/impl/src/main/res/values-cs/translations.xml b/libraries/push/impl/src/main/res/values-cs/translations.xml index d0f83fd311..d8ef70452e 100644 --- a/libraries/push/impl/src/main/res/values-cs/translations.xml +++ b/libraries/push/impl/src/main/res/values-cs/translations.xml @@ -38,6 +38,7 @@ "Rychlá odpověď" "Vás pozval(a) do místnosti" "Já" + "%1$s zmínil(a) nebo odpověděl(a)" "Prohlížíte si oznámení! Klikněte na mě!" "%1$s: %2$s" "%1$s: %2$s %3$s" diff --git a/libraries/push/impl/src/main/res/values-et/translations.xml b/libraries/push/impl/src/main/res/values-et/translations.xml index 55e591f8d4..cda5b2649f 100644 --- a/libraries/push/impl/src/main/res/values-et/translations.xml +++ b/libraries/push/impl/src/main/res/values-et/translations.xml @@ -34,6 +34,7 @@ "Kiirvastus" "Saatis sulle kutse jututuppa" "Mina" + "%1$s mainis või vastas" "See ongi teavitus! Klõpsi mind!" "%1$s: %2$s" "%1$s: %2$s %3$s" diff --git a/libraries/push/impl/src/main/res/values-hu/translations.xml b/libraries/push/impl/src/main/res/values-hu/translations.xml index d4f4a2caa6..5995aa0bec 100644 --- a/libraries/push/impl/src/main/res/values-hu/translations.xml +++ b/libraries/push/impl/src/main/res/values-hu/translations.xml @@ -34,6 +34,7 @@ "Gyors válasz" "Meghívta, hogy csatlakozzon a szobához" "Én" + "%1$s megemlítette vagy válaszolt" "Az értesítést nézi! Kattintson ide!" "%1$s: %2$s" "%1$s: %2$s %3$s" diff --git a/libraries/push/impl/src/main/res/values-nl/translations.xml b/libraries/push/impl/src/main/res/values-nl/translations.xml index 7bb304d898..d9ed0161ed 100644 --- a/libraries/push/impl/src/main/res/values-nl/translations.xml +++ b/libraries/push/impl/src/main/res/values-nl/translations.xml @@ -21,12 +21,14 @@ "%d uitnodigingen" "Nodigde je uit om te chatten" + "Heeft je genoemd: %1$s" "Nieuwe berichten" "%d nieuw bericht" "%d nieuwe berichten" "Reageerde met %1$s" + "Markeren als gelezen" "Snel antwoord" "Nodigde je uit om tot de kamer toe te treden" "Mij" 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 a0639b695b..8074371ea5 100644 --- a/libraries/push/impl/src/main/res/values-sk/translations.xml +++ b/libraries/push/impl/src/main/res/values-sk/translations.xml @@ -38,6 +38,7 @@ "Rýchla odpoveď" "Vás pozval do miestnosti" "Ja" + "%1$s spomenul/a alebo odpovedal/a" "Prezeráte si oznámenie! Kliknite na mňa!" "%1$s: %2$s" "%1$s: %2$s %3$s" 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 91c45ebe2e..fb20d4edbf 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -114,6 +114,7 @@ "Дакраніцеся, каб убачыць параметры" "Паўтарыць спробу" "Адмацаваць" + "Прагляд у хроніцы" "Прагляд зыходнага кода" "Так" "Аб праграме" @@ -180,6 +181,7 @@ "Людзі" "Пастаянная спасылка" "Дазвол" + "Замацаваны" "Калі ласка, пачакайце…" "Вы ўпэўнены, што хочаце скончыць гэтае апытанне?" "Апытанне: %1$s" 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 7c901b0422..6fcecc495b 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -114,6 +114,7 @@ "Klepnutím zobrazíte možnosti" "Zkusit znovu" "Odepnout" + "Zobrazit na časové ose" "Zobrazit zdroj" "Ano" "O aplikaci" @@ -180,6 +181,7 @@ Důvod: %1$s." "Lidé" "Trvalý odkaz" "Oprávnění" + "Připnuto" "Počkejte prosím…" "Opravdu chcete ukončit toto hlasování?" "Hlasování: %1$s" @@ -264,6 +266,7 @@ Důvod: %1$s." "Některé zprávy nebyly odeslány" "Omlouváme se, došlo k chybě" "Autenticitu této zašifrované zprávy nelze na tomto zařízení zaručit." + "Zašifrováno dříve ověřeným uživatelem." "Není zašifrováno." "Šifrováno neznámým nebo smazaným zařízením." "Šifrováno zařízením, které nebylo ověřeno jeho vlastníkem." @@ -283,6 +286,8 @@ Důvod: %1$s." "%1$d Připnutých zpráv" "Připnuté zprávy" + "Chystáte se přejít na svůj %1$s účet a obnovit svou identitu. Poté budete přesměrováni zpět do aplikace." + "Nemůžete to potvrdit? Přejděte na svůj účet a resetujte svou identitu." "Připnuté zprávy" "Nahrání média se nezdařilo, zkuste to prosím znovu." "Nepodařilo se načíst údaje o uživateli" 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 56c541cc48..dcd41ca7a6 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -277,7 +277,7 @@ Grund: %1$s." "Blockierung aufheben" "Der Nutzer kann dir wieder Nachrichten senden & alle Nachrichten des Nutzers werden wieder angezeigt." "Blockierung aufheben" - "%1$svon %2$s" + "%1$s von %2$s" "%1$s Angepinnte Nachrichten" "Alle anzeigen" "Chat" 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 4dace2a902..8f6c8740e6 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -112,6 +112,7 @@ "Valikuteks klõpsa" "Proovi uuesti" "Eemalda esiletõstmine" + "Vaata ajajoonel" "Vaata lähtekoodi" "Jah" "Rakenduse teave" @@ -177,6 +178,7 @@ Põhjus: %1$s." "Inimesed" "Püsilink" "Õigus" + "Esiletõstetud" "Palun oota…" "Kas oled kindel, et soovid selle küsitluse lõpetada?" "Küsitlus: %1$s" @@ -260,6 +262,7 @@ Põhjus: %1$s." "Mõned sõnumid on saatmata" "Vabandust, ilmnes viga" "Selle krüptitud sõnumi tõepärasus pole selles seadmes tagatud." + "Krüptitud varem verifitseeritud kasutaja poolt" "Pole krüptitud." "Krüptitud tundmatu või kustutatud seadme poolt." "Krüptitud seadme poolt, mida tema omanik pole verifitseerinud." @@ -278,6 +281,8 @@ Põhjus: %1$s." "%1$d esiletõstetud sõnumit" "Esiletõstetud sõnumid" + "Oma võrguidentiteedi lähtestamiseks suuname sind %1$s kasutajakonto halduse lehele. Hiljem suunatakse sind tagasi sama rakenduse juurde." + "Sa ei saa seda kinnitada? Ava oma kasutajakonto haldus ja lähtesta oma võrguidentiteet." "Esiletõstetud sõnumid" "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Kasutaja andmete laadimine ei õnnestunud" 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 8d39970ad7..0e11f3f37e 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -111,6 +111,7 @@ "Appuyez pour afficher les options" "Essayer à nouveau" "Désépingler" + "Voir dans la discussion" "Afficher la source" "Oui" "À propos" @@ -176,6 +177,7 @@ Raison: %1$s." "Personnes" "Permalien" "Autorisation" + "Épinglé" "Veuillez patienter…" "Êtes-vous sûr de vouloir mettre fin à ce sondage ?" "Sondage : %1$s" 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 17468d55dc..fff7fcbe20 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -112,6 +112,7 @@ "Koppintson a beállításokért" "Próbálja újra" "Kitűzés feloldása" + "Megtekintés az idővonalon" "Forrás megtekintése" "Igen" "Névjegy" @@ -177,6 +178,7 @@ Ok: %1$s." "Emberek" "Állandó hivatkozás" "Engedély" + "Kitűzve" "Kis türelmet…" "Biztos, hogy befejezi ezt a szavazást?" "Szavazás: %1$s" @@ -260,6 +262,7 @@ Ok: %1$s." "Néhány üzenet nem került elküldésre" "Elnézést, hiba történt" "A titkosított üzenetek valódiságát ezen az eszközön nem lehet garantálni." + "Egy korábban ellenőrzött felhasználó által titkosítva." "Nincs titkosítva." "Ismeretlen vagy törölt eszköz által titkosítva." "A tulajdonos által nem ellenőrzött eszköz által titkosítva." @@ -271,6 +274,15 @@ Ok: %1$s." "Nem sikerült kiválasztani a médiát, próbálja újra." "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra." "Nem sikerült a média feltöltése, próbálja újra." + "Nyomjon hosszan az üzenetre, és válassza a „%1$s” lehetőséget, hogy itt szerepeljen." + "Tűzze ki a fontos üzeneteket, hogy könnyen felfedezhetők legyenek" + + "%1$d kitűzött üzenet" + "%1$d kitűzött üzenet" + + "Kitűzött üzenetek" + "Arra készül, hogy belépjen a(z) %1$s fiókjába, hogy visszaállítsa a személyazonosságát. Ezután vissza fog térni az alkalmazásba." + "Nem tudja megerősíteni? Ugorjon a fiókjához, és állítsa vissza a személyazonosságát." "Kitűzött üzenetek" "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra." "Nem sikerült letölteni a felhasználói adatokat" 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 d4e650c1f5..7b9034291f 100644 --- a/libraries/ui-strings/src/main/res/values-nl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nl/translations.xml @@ -1,6 +1,10 @@ "Verwijderen" + + "%1$d cijfer ingevoerd" + "%1$d cijfers ingevoerd" + "Wachtwoord verbergen" "Spring naar einde" "Alleen vermeldingen" @@ -14,6 +18,10 @@ "Reageer met %1$s" "Reageer met andere emoji\'s" "Gelezen door %1$s en %2$s" + + "Gelezen door %1$s en %2$d andere" + "Gelezen door %1$s en %2$d anderen" + "Gelezen door %1$s" "Tik om alles weer te geven" "Verwijder reactie met %1$s" @@ -22,6 +30,7 @@ "Begin een oproep" "Gebruikersmenu" "Spraakbericht opnemen." + "Opnemen stoppen" "Accepteren" "Toevoegen aan tijdlijn" "Terug" @@ -38,12 +47,14 @@ "Aanmaken" "Creëer een kamer" "Weigeren" + "Peiling verwijderen" "Uitschakelen" "Gereed" "Bewerken" "Peiling wijzigen" "Activeren" "Peiling beëindigen" + "Voer pincode in" "Wachtwoord vergeten?" "Doorsturen" "Uitnodigen" @@ -54,7 +65,9 @@ "Deelnemen" "Meer informatie" "Verlaten" + "Gesprek verlaten" "Ruimte verlaten" + "Meer laden" "Account beheren" "Apparaten beheren" "Volgende" @@ -88,25 +101,35 @@ "Verificatie starten" "Tik om kaart te laden" "Foto maken" + "Tik voor opties" + "Probeer het opnieuw" "Bron weergeven" "Ja" "Over" "Beleid inzake redelijk gebruik" "Geavanceerde instellingen" + "Weergave" "Geluid" + "Geblokkeerde gebruikers" "Bubbels" "Chat back-up" "Copyright" "Kamer maken…" "Heeft de kamer verlaten" + "Donker" "Decryptie fout" "Ontwikkelaarsopties" + "Directe chat" "(bewerkt)" "Bewerken" "* %1$s %2$s" "Encryptie ingeschakeld" + "Voer je pincode in" "Fout" "Iedereen" + "Mislukt" + "Favoriet" + "Favoriet gemarkeerd" "Bestand" "Bestand opgeslagen in Downloads" "Bericht doorsturen" @@ -116,6 +139,7 @@ "APK installeren" "Deze Matrix-ID kan niet worden gevonden, dus de uitnodiging is mogelijk niet ontvangen." "De kamer verlaten" + "Licht" "Link gekopieerd naar klembord" "Laden…" @@ -123,12 +147,14 @@ "%1$d leden" "Bericht" + "Berichtacties" "Berichtindeling" "Bericht verwijderd" "Modern" "Dempen" "Geen resultaten" "Offline" + "of" "Wachtwoord" "Personen" "Permalink" @@ -144,25 +170,35 @@ "Privacybeleid" "Reactie" "Reacties" - "Recovery key" + "Herstelsleutel" "Verversen…" + "Reageren op %1$s" "Een fout melden" + "Meld een probleem" "Melding ingediend" "Uitgebreide tekstverwerker" + "Kamer" "Naam van de kamer" "bijv. de naam van je project" + "Schermvergrendeling" + "Iemand zoeken" "Zoekresultaten" "Beveiliging" + "Gezien door" "Verzenden…" + "Verzenden mislukt" + "Verzonden" "Server niet ondersteund" "Server-URL" "Instellingen" "Gedeelde locatie" + "Uitloggen" "Chat starten…" "Sticker" "Geslaagd" "Suggesties" "Synchroniseren" + "Systeem" "Tekst" "Kennisgevingen van derden" "Subchat" @@ -171,14 +207,17 @@ "Kan niet ontsleutelen" "Uitnodigingen konden niet naar een of meerdere gebruikers worden verzonden." "Kan uitnodiging(en) niet verzenden" + "Ontgrendelen" "Dempen opheffen" "Niet-ondersteunde gebeurtenis" "Gebruikersnaam" "Verificatie geannuleerd" "Verificatie voltooid" + "Apparaat verifiëren" "Video" "Spraakbericht" "Wachten…" + "Wachten op dit bericht" "Bevestiging" "Fout" "Geslaagd" @@ -187,8 +226,10 @@ "%1$s kon de kaart niet laden. Probeer het later opnieuw." "Het laden van berichten is mislukt" "%1$s had geen toegang tot je locatie. Probeer het later opnieuw." + "Het uploaden van je spraakbericht is mislukt." "%1$s heeft geen toegang tot je locatie. Je kunt dit inschakelen bij Instellingen." "%1$s heeft geen toegang tot je locatie. Schakel toegang hieronder in." + "%1$s heeft geen toegang tot je microfoon. Schakel toegang in om een spraakbericht op te nemen." "Sommige berichten zijn niet verzonden" "Sorry, er is een fout opgetreden" "🔐️ Sluit je bij mij aan op %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 37866d0d09..16c2973b08 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -114,6 +114,7 @@ "Нажмите для просмотра вариантов" "Повторить попытку" "Открепить" + "Просмотр в хронологии" "Показать источник" "Да" "О приложении" @@ -180,6 +181,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 c300012026..5fbe3c55e7 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -114,6 +114,7 @@ "Klepnutím získate možnosti" "Skúste to znova" "Odopnúť" + "Zobraziť na časovej osi" "Zobraziť zdroj" "Áno" "O aplikácii" @@ -180,6 +181,7 @@ Dôvod: %1$s." "Ľudia" "Trvalý odkaz" "Povolenie" + "Pripnuté" "Prosím, počkajte…" "Ste si istí, že chcete ukončiť túto anketu?" "Anketa: %1$s" @@ -264,6 +266,7 @@ Dôvod: %1$s." "Niektoré správy neboli odoslané" "Prepáčte, vyskytla sa chyba" "Pravosť tejto šifrovanej správy nie je možné zaručiť na tomto zariadení." + "Šifrované predtým overeným používateľom." "Nie je šifrované." "Zašifrované neznámym alebo odstráneným zariadením." "Šifrované zariadením, ktoré nie je overené jeho majiteľom." @@ -283,6 +286,8 @@ Dôvod: %1$s." "%1$d pripnutých správ" "Pripnuté správy" + "Chystáte sa prejsť na svoj %1$s účet, aby ste obnovili svoju identitu. Potom budete vrátení späť do aplikácie." + "Neviete potvrdiť? Prejdite do svojho účtu a obnovte svoju identitu." "Pripnuté správy" "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 76176e2070..ee333c84b2 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -112,6 +112,7 @@ "Tryck för alternativ" "Försök igen" "Frigör" + "Visa i tidslinjen" "Visa källkod" "Ja" "Om" @@ -177,6 +178,7 @@ Anledning:%1$s." "Personer" "Permalänk" "Behörighet" + "Fäst" "Vänligen vänta …" "Är du säker på att du vill avsluta den här omröstningen?" "Omröstning: %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 501843bffb..f7c3213ba4 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -262,6 +262,7 @@ Reason: %1$s." "Some messages have not been sent" "Sorry, an error occurred" "The authenticity of this encrypted message can\'t be guaranteed on this device." + "Encrypted by a previously-verified user." "Not encrypted." "Encrypted by an unknown or deleted device." "Encrypted by a device not verified by its owner." @@ -280,6 +281,8 @@ Reason: %1$s." "%1$d Pinned messages" "Pinned messages" + "You\'re about to go to your %1$s account to reset your identity. Afterwards you\'ll be taken back to the app." + "Can\'t confirm? Go to your account to reset your identity." "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" diff --git a/screenshots/de/features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_de.png b/screenshots/de/features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_de.png deleted file mode 100644 index 17a1dda8db..0000000000 --- a/screenshots/de/features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e178a484e92a09df25b821668d84f6971e3c1cffdaf5c26e959b9308803ca388 -size 15637 diff --git a/screenshots/de/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_de.png b/screenshots/de/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_de.png new file mode 100644 index 0000000000..4cdefe54cc --- /dev/null +++ b/screenshots/de/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:02591eb63947314eddd09de39ba90c33858465f7bff3152b47cd1a1e7939f0e9 +size 21338 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png index bd8e14bc75..45e12f3a55 100644 --- a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b62714a26902c5988014283a58014f3da0df923130fd205e0f8f58a5bf2fb1d -size 12270 +oid sha256:fbde48ee83556732d471117ce850a54d28753e42fbb2f934baa70df12d728d93 +size 12221 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_de.png index c8734317ec..2727ca4d1f 100644 --- a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_de.png +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e14151400116f1244b5efe894e62a0efecfc6ecb89d795df3b863df9761621d0 -size 13313 +oid sha256:b44fd60d6a2f04d0378cf8d6915a67ec419234f77bc2b3def03d383ddcd2ba29 +size 13104 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_de.png index f5875c7909..408dd84152 100644 --- a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_de.png +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a72e722cd5d033389fd2ed6957c023e7e642ea7e0a69cb7bc8464eb0d01bda61 -size 13284 +oid sha256:b18307b48cb95912a6af7439abb757a08c511855762c10f3cc7e2524d49b7801 +size 13097 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_de.png index 8dcfe397b5..102130d9ab 100644 --- a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_de.png +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:175fbc008939c2c2c725fcc0a968a2b3e06d2dbaa2151e7cb73652c73d67e510 -size 13280 +oid sha256:e93463566bbb3bd6ffabced5c18b555d6b4c5474523981e7cd3b5df102e35922 +size 13068 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_de.png index d9a3df1826..1565b5f8e1 100644 --- a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_de.png +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:93d4ed6e6240dd043a34f14e4927c2490e4459df5cee50c01d2aa020a96fe0b2 -size 13395 +oid sha256:f8e37b013817e552a181017a1682c5fdfcb0f5607d6980c0abf95d36f20c68fe +size 13202 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_de.png index aecd7dd6a4..1688d6fd47 100644 --- a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_de.png +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f28a49bbfeef2dfbbfe1e985e8e9b818a2faa82e99c033ab8db9783ae911ee70 -size 13430 +oid sha256:7fd1b4d307180c8c6bc43a8f214a18f02a6bbac216110d231c3dd4289da0a5cd +size 13223 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_de.png index 5090aa2799..d3505dd49a 100644 --- a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_de.png +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f97467b5e28fb8a6f020c69077c1d6c3577db04ce9c7ba038458e31aaee0aa4 -size 13338 +oid sha256:bb5a9048b3f237d5f34e5720beb6373bfd2e85795c3d0d86ddf59d171ffeac97 +size 13145 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_13_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_13_de.png index e58b69d861..57739165dd 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_13_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e05dbc49ff614d8012f3e57bbafce0cf295e59834fe1bd404b91a2de957199a9 -size 60307 +oid sha256:868098ba78d6ab7715de6ef85f928ecf40b046fccc7622fe33a3e7d122755a18 +size 60112 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png index 47b507ade4..917a84f862 100644 --- a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dfdf3c021f14f4e065d3fccb225558c41c68d73a9ce03fade1409b9abd22b13d -size 28429 +oid sha256:8ce2351412f17348c5fbc94c1e77fc6f70e6aa6fe118041ff29692f1f19f815f +size 27939 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png index 37cc4e9e0d..0218d8dc9a 100644 --- a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf0cc1be1261344e1e775aab9e33a5e72a0b7b1c07b7118ec3cf03dd7b1c86df -size 27325 +oid sha256:a4c7f50bd4bb194c26fdb8fca8b3f733255d30804a035e4b1269e31494419744 +size 26944 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png index 37cc4e9e0d..0218d8dc9a 100644 --- a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf0cc1be1261344e1e775aab9e33a5e72a0b7b1c07b7118ec3cf03dd7b1c86df -size 27325 +oid sha256:a4c7f50bd4bb194c26fdb8fca8b3f733255d30804a035e4b1269e31494419744 +size 26944 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png index a7e9f5c992..c068c315bf 100644 --- a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:005d321ea138e0f6161ae1964982a7bd77ad539af88fc377712a789458d2b928 -size 39887 +oid sha256:836d97a08320f602807201ac740eb417ba173ddfd4821455f9d85ca8945c0d64 +size 39351 diff --git a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png index 405b450e89..fd704a7768 100644 --- a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ebdd281a030aa9200cc026abdbbb17ce55a43967a1efb8f8ee6b8e1394cde41 -size 63258 +oid sha256:10c1eaf4d2ea7039d415a86f848838a1bb2044759517f894108d35ddc8d5a295 +size 62509 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 338273e743..cf40a7bf10 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,42 +1,42 @@ // 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",19951,], -["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19951,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19958,], +["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19958,], ["features.invite.impl.response_AcceptDeclineInviteView_Day_0_en","features.invite.impl.response_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19951,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19951,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19951,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19951,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19958,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19958,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19958,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19958,], ["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_4_en","features.login.impl.accountprovider_AccountProviderView_Night_4_en",0,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19951,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19951,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19951,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19951,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19951,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19951,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19951,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19951,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",19954,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",19954,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19951,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19951,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19951,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19951,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19958,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19958,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19958,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19958,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19958,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19958,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19958,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19958,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",19958,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",19958,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19958,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19958,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19958,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19958,], ["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",19951,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",19958,], ["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",19951,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",19958,], ["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",19951,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",19958,], ["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",19951,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19958,], ["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,], @@ -46,11 +46,11 @@ 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","",19951,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19951,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19951,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19951,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19951,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",19958,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19958,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19958,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19958,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19958,], ["libraries.designsystem.components.avatar_Avatar_Avatars_0_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_10_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_11_en","",0,], @@ -130,13 +130,13 @@ export const screenshots = [ ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], ["libraries.designsystem.components_BigCheckmark_Day_0_en","libraries.designsystem.components_BigCheckmark_Night_0_en",0,], ["libraries.designsystem.components_BigIcon_Day_0_en","libraries.designsystem.components_BigIcon_Night_0_en",0,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19951,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19951,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19951,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19951,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19951,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19951,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19951,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19958,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19958,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19958,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19958,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19958,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19958,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19958,], ["libraries.designsystem.components_BloomInitials_Day_0_en","libraries.designsystem.components_BloomInitials_Night_0_en",0,], ["libraries.designsystem.components_BloomInitials_Day_1_en","libraries.designsystem.components_BloomInitials_Night_1_en",0,], ["libraries.designsystem.components_BloomInitials_Day_2_en","libraries.designsystem.components_BloomInitials_Night_2_en",0,], @@ -147,84 +147,84 @@ export const screenshots = [ ["libraries.designsystem.components_BloomInitials_Day_7_en","libraries.designsystem.components_BloomInitials_Night_7_en",0,], ["libraries.designsystem.components_Bloom_Day_0_en","libraries.designsystem.components_Bloom_Night_0_en",0,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19951,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19951,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19951,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19951,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19951,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19958,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19958,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19958,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19958,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19958,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_0_en","features.call.impl.ui_CallScreenPipView_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_1_en","features.call.impl.ui_CallScreenPipView_Night_1_en",0,], ["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,], -["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19951,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19951,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19951,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19951,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19951,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19951,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19951,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19951,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19951,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19951,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19951,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19958,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19958,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19958,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19958,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19958,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19958,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19958,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19958,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19958,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19958,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19958,], ["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",19951,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19951,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",19958,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19958,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19951,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19958,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], ["libraries.textcomposer.components_ComposerOptionsButton_Day_0_en","libraries.textcomposer.components_ComposerOptionsButton_Night_0_en",0,], ["libraries.designsystem.components.avatar_CompositeAvatar_Avatars_en","",0,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19951,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19951,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19958,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19958,], ["features.preferences.impl.developer.tracing_ConfigureTracingView_Day_0_en","features.preferences.impl.developer.tracing_ConfigureTracingView_Night_0_en",0,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19951,], -["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19951,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19958,], +["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19958,], ["libraries.designsystem.components.dialogs_ConfirmationDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ConfirmationDialog_Day_0_en","libraries.designsystem.components.dialogs_ConfirmationDialog_Night_0_en",0,], ["features.networkmonitor.api.ui_ConnectivityIndicatorView_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicatorView_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19951,], -["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19951,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19951,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19951,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19951,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19951,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19951,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19951,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19951,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19951,], -["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19951,], -["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19951,], -["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19951,], -["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19951,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19951,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19951,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19958,], +["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19958,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19958,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19958,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19958,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19958,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19958,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19958,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19958,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19958,], +["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19958,], +["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19958,], +["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19958,], +["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19958,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19958,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19958,], ["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",19951,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19951,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19951,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",19958,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19958,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19958,], ["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",19951,], -["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19951,], -["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19951,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19951,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19951,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19951,], -["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19951,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",19958,], +["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19958,], +["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19958,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19958,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19958,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19958,], +["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19958,], ["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,], @@ -236,12 +236,12 @@ export const screenshots = [ ["libraries.designsystem.text_DpScale_1_0f__en","",0,], ["libraries.designsystem.text_DpScale_1_5f__en","",0,], ["libraries.designsystem.theme.components_DropdownMenuItem_Menus_en","",0,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19951,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19951,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19951,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19951,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19951,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19951,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19958,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19958,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19958,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19958,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19958,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19958,], ["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,], @@ -251,10 +251,10 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiPicker_Night_0_en",0,], -["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19951,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19951,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19951,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19951,], +["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19958,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19958,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19958,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19958,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], ["libraries.designsystem.theme.components_FilledButtonLargeLowPadding_Buttons_en","",0,], @@ -265,15 +265,15 @@ export const screenshots = [ ["libraries.designsystem.theme.components_FloatingActionButton_Floating Action Buttons_en","",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19951,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19951,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19951,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19958,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19958,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19958,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_0_en","features.messages.impl.forward_ForwardMessagesView_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_1_en","features.messages.impl.forward_ForwardMessagesView_Night_1_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_2_en","features.messages.impl.forward_ForwardMessagesView_Night_2_en",0,], -["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19951,], -["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19951,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19958,], +["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19958,], ["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,], @@ -300,37 +300,37 @@ 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",19951,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",19958,], ["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",19951,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",19958,], ["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",19951,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",19958,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19951,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19958,], ["features.joinroom.impl_JoinRoomView_Day_0_en","features.joinroom.impl_JoinRoomView_Night_0_en",0,], ["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",0,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19951,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19951,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19951,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19951,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19951,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19951,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19951,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19951,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19951,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19958,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19958,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19958,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19958,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19958,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19958,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19958,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19958,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19958,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["libraries.designsystem.components_LabelledOutlinedTextField_Day_0_en","libraries.designsystem.components_LabelledOutlinedTextField_Night_0_en",0,], ["libraries.designsystem.components_LabelledTextField_Day_0_en","libraries.designsystem.components_LabelledTextField_Night_0_en",0,], ["features.leaveroom.api_LeaveRoomView_Day_0_en","features.leaveroom.api_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19951,], -["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19951,], -["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19951,], -["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19951,], -["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19951,], -["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19951,], +["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19958,], +["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19958,], +["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19958,], +["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19958,], +["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19958,], +["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19958,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], @@ -381,28 +381,28 @@ 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",19951,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19951,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19951,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19951,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19958,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19958,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19958,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19958,], ["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",19951,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19951,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19951,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19951,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19951,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19951,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19951,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19951,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19951,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19951,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19951,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19951,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19951,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19951,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19951,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",19958,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19958,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19958,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19958,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19958,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19958,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19958,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19958,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19958,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19958,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19958,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19958,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19958,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19958,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19958,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19951,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19958,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en","libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_0_en","libraries.matrix.ui.components_MatrixUserHeader_Night_0_en",0,], @@ -412,7 +412,7 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_10_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19951,], +["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19958,], ["libraries.mediaviewer.api.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_5_en","",0,], @@ -422,10 +422,9 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_9_en","",0,], ["libraries.designsystem.theme.components_MediumTopAppBar_App Bars_en","",0,], ["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,], -["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19951,], ["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",19951,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",19958,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_10_en","features.messages.impl.timeline.components_MessageEventBubble_Night_10_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_11_en","features.messages.impl.timeline.components_MessageEventBubble_Night_11_en",0,], @@ -442,7 +441,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_8_en","features.messages.impl.timeline.components_MessageEventBubble_Night_8_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_9_en","features.messages.impl.timeline.components_MessageEventBubble_Night_9_en",0,], -["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",19954,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",19958,], ["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,], @@ -450,26 +449,26 @@ 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.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19951,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19951,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",19954,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19954,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19951,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19951,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19954,], -["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",19954,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",19954,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19951,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19951,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19951,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19954,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19951,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19951,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19951,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19951,], -["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19951,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19958,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19958,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",19958,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19958,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19958,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19958,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19958,], +["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",19958,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",19958,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19958,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19958,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19958,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19958,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19958,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19958,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19958,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19958,], +["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19958,], ["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",19951,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",19958,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -478,28 +477,28 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple selection List item - selection in trailing content_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple selection List item - selection in supporting text_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple selection List item - no selection_List items_en","",0,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19951,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19951,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19951,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19958,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19958,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19958,], ["libraries.oidc.impl.webview_OidcView_Day_0_en","libraries.oidc.impl.webview_OidcView_Night_0_en",0,], ["libraries.oidc.impl.webview_OidcView_Day_1_en","libraries.oidc.impl.webview_OidcView_Night_1_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19951,], -["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19951,], -["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19951,], -["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19951,], -["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19951,], +["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19958,], +["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19958,], +["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19958,], +["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19958,], +["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19958,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], @@ -514,57 +513,57 @@ export const screenshots = [ ["libraries.designsystem.components_PageTitleWithIconFull_Day_3_en","libraries.designsystem.components_PageTitleWithIconFull_Night_3_en",0,], ["libraries.designsystem.components_PageTitleWithIconFull_Day_4_en","libraries.designsystem.components_PageTitleWithIconFull_Night_4_en",0,], ["libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en","libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en",0,], -["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19951,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19951,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19951,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19951,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19951,], +["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19958,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19958,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19958,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19958,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19958,], ["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",19951,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19951,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19951,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19958,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19958,], ["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_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",19954,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",19954,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",19954,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",19954,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",19954,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",19954,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",19954,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",19954,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",19958,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",19958,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",19958,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",19958,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",19958,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",19958,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",19958,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",19958,], ["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",19951,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19951,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19951,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19951,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19951,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19958,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19958,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19958,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19958,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19958,], ["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",19951,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19951,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19951,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19951,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19951,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19951,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19951,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19951,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19951,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19951,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19951,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",19958,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19958,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19958,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19958,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19958,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19958,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19958,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19958,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19958,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19958,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19958,], ["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceDivider_Preferences_en","",0,], @@ -580,188 +579,188 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceTextLight_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19951,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19951,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19951,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19951,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19958,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19958,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19958,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19958,], ["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","",19951,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19951,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19951,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19951,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19951,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19951,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19951,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19951,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19951,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19951,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19951,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19951,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19951,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19951,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19951,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19951,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19951,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19951,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",19958,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19958,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19958,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19958,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19958,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19958,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19958,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19958,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19958,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19958,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19958,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19958,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19958,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19958,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19958,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19958,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19958,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19958,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19951,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19951,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19958,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19958,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19951,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19951,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19951,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19951,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19951,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19951,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19951,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19958,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19958,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19958,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19958,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19958,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19958,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19958,], ["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",19951,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19951,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19951,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19951,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19951,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19951,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",19954,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",19954,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",19954,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",19954,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19958,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19958,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19958,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19958,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19958,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19958,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",19958,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",19958,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",19958,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",19958,], ["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",0,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",19954,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19951,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19951,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19951,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19951,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19951,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19951,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19951,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19951,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19951,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19951,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",19958,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19958,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19958,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19958,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19958,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19958,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19958,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19958,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19958,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19958,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19958,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19951,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19958,], ["features.roomdetails.impl.components_RoomBadgeNegative_Day_0_en","features.roomdetails.impl.components_RoomBadgeNegative_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgeNeutral_Day_0_en","features.roomdetails.impl.components_RoomBadgeNeutral_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgePositive_Day_0_en","features.roomdetails.impl.components_RoomBadgePositive_Night_0_en",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",19951,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",19951,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19951,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19951,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19951,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19951,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19951,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19951,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19951,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19951,], -["features.roomdetails.impl_RoomDetails_0_en","",19951,], -["features.roomdetails.impl_RoomDetails_10_en","",19951,], -["features.roomdetails.impl_RoomDetails_11_en","",19951,], -["features.roomdetails.impl_RoomDetails_12_en","",19951,], -["features.roomdetails.impl_RoomDetails_1_en","",19951,], -["features.roomdetails.impl_RoomDetails_2_en","",19951,], -["features.roomdetails.impl_RoomDetails_3_en","",19951,], -["features.roomdetails.impl_RoomDetails_4_en","",19951,], -["features.roomdetails.impl_RoomDetails_5_en","",19951,], -["features.roomdetails.impl_RoomDetails_6_en","",19951,], -["features.roomdetails.impl_RoomDetails_7_en","",19951,], -["features.roomdetails.impl_RoomDetails_8_en","",19951,], -["features.roomdetails.impl_RoomDetails_9_en","",19951,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19951,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19951,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19951,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19951,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19951,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19951,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19951,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19951,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19951,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19951,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19951,], -["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19951,], -["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19951,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",19958,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",19958,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19958,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19958,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19958,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19958,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19958,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19958,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19958,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19958,], +["features.roomdetails.impl_RoomDetails_0_en","",19958,], +["features.roomdetails.impl_RoomDetails_10_en","",19958,], +["features.roomdetails.impl_RoomDetails_11_en","",19958,], +["features.roomdetails.impl_RoomDetails_12_en","",19958,], +["features.roomdetails.impl_RoomDetails_1_en","",19958,], +["features.roomdetails.impl_RoomDetails_2_en","",19958,], +["features.roomdetails.impl_RoomDetails_3_en","",19958,], +["features.roomdetails.impl_RoomDetails_4_en","",19958,], +["features.roomdetails.impl_RoomDetails_5_en","",19958,], +["features.roomdetails.impl_RoomDetails_6_en","",19958,], +["features.roomdetails.impl_RoomDetails_7_en","",19958,], +["features.roomdetails.impl_RoomDetails_8_en","",19958,], +["features.roomdetails.impl_RoomDetails_9_en","",19958,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19958,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19958,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19958,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19958,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19958,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19958,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19958,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19958,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19958,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19958,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19958,], +["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19958,], +["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19958,], ["features.roomlist.impl.components_RoomListContentView_Day_2_en","features.roomlist.impl.components_RoomListContentView_Night_2_en",0,], -["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19951,], -["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19951,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19951,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19951,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19951,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19951,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19951,], +["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19958,], +["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19958,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19958,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19958,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19958,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19958,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19958,], ["features.roomlist.impl.search_RoomListSearchContent_Day_0_en","features.roomlist.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19951,], -["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19951,], -["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19951,], +["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19958,], +["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19958,], +["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19958,], ["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",0,], -["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19951,], -["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19951,], -["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19951,], -["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19951,], -["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19951,], -["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19951,], -["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19951,], +["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19958,], +["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19958,], +["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19958,], +["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19958,], +["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19958,], +["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19958,], +["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19958,], ["features.roomlist.impl_RoomListView_Day_8_en","features.roomlist.impl_RoomListView_Night_8_en",0,], -["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19951,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19951,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19951,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19951,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19951,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19951,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19951,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19951,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19951,], +["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19958,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19958,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19958,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19958,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19958,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19958,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19958,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19958,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19958,], ["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19951,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19951,], -["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19951,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19958,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19958,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19958,], ["libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Day_0_en","libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Night_0_en",0,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19951,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19951,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19951,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19951,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19951,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19951,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19951,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19951,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19951,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19958,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19958,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19958,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19958,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19958,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19958,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19958,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19958,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19958,], ["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_9_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19951,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19951,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19951,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19951,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19951,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19951,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19951,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19951,], -["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19951,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19951,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19951,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19951,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19951,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19951,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19951,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19958,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19958,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19958,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19958,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19958,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19958,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19958,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19958,], +["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19958,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19958,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19958,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19958,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19958,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19958,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19958,], ["features.roomlist.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.roomlist.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_0_en","features.roomlist.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_10_en","features.roomlist.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -784,10 +783,10 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_26_en","features.roomlist.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_27_en","features.roomlist.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_28_en","features.roomlist.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19951,], -["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19951,], -["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19951,], -["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19951,], +["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19958,], +["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19958,], +["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19958,], +["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19958,], ["features.roomlist.impl.components_RoomSummaryRow_Day_3_en","features.roomlist.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_4_en","features.roomlist.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_5_en","features.roomlist.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -795,64 +794,64 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_7_en","features.roomlist.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_8_en","features.roomlist.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_9_en","features.roomlist.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19951,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19951,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19951,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19958,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19958,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19958,], ["appicon.element_RoundIcon_en","",0,], ["appicon.enterprise_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",19951,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19951,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19951,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",19958,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19958,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19958,], ["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","",19951,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search views_en","",19958,], ["libraries.designsystem.theme.components_SearchBarActiveWithQueryNoBackButton_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithQuery_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarInactive_Search views_en","",0,], -["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19951,], -["features.createroom.impl.components_SearchSingleUserResultItem_en","",19951,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19951,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19951,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19951,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19951,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19951,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19951,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19951,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19951,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19951,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19951,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19951,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19951,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19951,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19951,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19951,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19951,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19951,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19951,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19951,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19951,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19951,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19951,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19951,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19951,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19951,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19951,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19951,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19951,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19951,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19951,], +["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19958,], +["features.createroom.impl.components_SearchSingleUserResultItem_en","",19958,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19958,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19958,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19958,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19958,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19958,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19958,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19958,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19958,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19958,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19958,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19958,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19958,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19958,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19958,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19958,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19958,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19958,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19958,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19958,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19958,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19958,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19958,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19958,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19958,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19958,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19958,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19958,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19958,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19958,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19958,], ["libraries.matrix.ui.components_SelectedRoom_Day_0_en","libraries.matrix.ui.components_SelectedRoom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoom_Day_1_en","libraries.matrix.ui.components_SelectedRoom_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en","libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUser_Day_0_en","libraries.matrix.ui.components_SelectedUser_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19951,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19951,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19951,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19951,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19951,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19958,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19958,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19958,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19958,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19958,], ["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,], @@ -862,38 +861,38 @@ 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.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19951,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19951,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19951,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19951,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19951,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19951,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19958,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19958,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19958,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19958,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19958,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19958,], ["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",19951,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",19958,], ["features.messages.impl.timeline.components.reactionsummary_SheetContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_SheetContent_Night_0_en",0,], ["features.messages.impl.actionlist_SheetContent_Day_0_en","features.messages.impl.actionlist_SheetContent_Night_0_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19951,], -["features.messages.impl.actionlist_SheetContent_Day_11_en","features.messages.impl.actionlist_SheetContent_Night_11_en",19954,], +["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19958,], +["features.messages.impl.actionlist_SheetContent_Day_11_en","features.messages.impl.actionlist_SheetContent_Night_11_en",19958,], ["features.messages.impl.actionlist_SheetContent_Day_1_en","features.messages.impl.actionlist_SheetContent_Night_1_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19951,], -["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19951,], -["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19951,], -["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19951,], -["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19951,], -["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19951,], -["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19951,], -["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19951,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19951,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19951,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19951,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19951,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19951,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19951,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19951,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19951,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19951,], +["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19958,], +["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19958,], +["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19958,], +["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19958,], +["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19958,], +["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19958,], +["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19958,], +["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19958,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19958,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19958,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19958,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19958,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19958,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19958,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19958,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19958,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19958,], ["libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en",0,], ["libraries.designsystem.components.list_SingleSelectionListItemCustomFormattert_Single selection List item - custom formatter_List items_en","",0,], @@ -902,7 +901,7 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single selection List item - no selection, supporting text_List items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single selection List item - no selection_List items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19951,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19958,], ["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,], @@ -912,36 +911,37 @@ export const screenshots = [ ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], ["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",0,], -["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19951,], +["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19958,], ["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",19961,], ["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",19951,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",19958,], ["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_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19951,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19951,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19951,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19951,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19951,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19951,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19951,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19958,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19958,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19958,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19958,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19958,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19958,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19958,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], ["libraries.designsystem.theme.components_TextFieldDark_TextFields_en","",0,], @@ -953,26 +953,26 @@ export const screenshots = [ ["libraries.designsystem.theme.components_TextFieldValueTextFieldDark_TextFields_en","",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19951,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19951,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19951,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19958,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19958,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19958,], ["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",19951,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19951,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",19958,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19958,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en",0,], ["features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en",0,], ["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_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19951,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19958,], ["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",19951,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19951,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19951,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",19958,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19958,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19958,], ["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,], @@ -980,16 +980,16 @@ 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",19951,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19951,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19958,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19958,], ["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_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19951,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19958,], ["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",19951,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19951,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",19958,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19958,], ["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,], @@ -998,36 +998,36 @@ 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",19951,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19958,], ["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",19951,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19958,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19951,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19958,], ["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_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19951,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19951,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19958,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19958,], ["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_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",19951,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",19958,], ["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",19951,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19951,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19951,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19951,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19951,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19958,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19958,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19958,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19958,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19958,], ["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",19951,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19951,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",19958,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19958,], ["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",19951,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",19958,], ["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,], @@ -1036,8 +1036,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",19951,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19951,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",19958,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19958,], ["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,], @@ -1049,7 +1049,7 @@ 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",19951,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",19958,], ["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,], @@ -1071,80 +1071,80 @@ 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",19954,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19951,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",19958,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19958,], ["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",19951,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19951,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19951,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19951,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19951,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19951,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19951,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19958,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19958,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19958,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19958,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19958,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19958,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19958,], ["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",19951,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",19958,], ["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",19951,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",19958,], ["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",19951,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",19958,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.theme.components_TopAppBar_App Bars_en","",0,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19951,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19951,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19951,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19951,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19951,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19951,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19951,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19951,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19958,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19958,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19958,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19958,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19958,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19958,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19958,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19958,], ["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",19951,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19951,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19951,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19951,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19951,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19951,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",19958,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19958,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19958,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19958,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19958,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19958,], ["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","",19951,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",19958,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19951,], -["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19951,], -["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19951,], -["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19951,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19958,], +["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19958,], +["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19958,], +["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19958,], ["features.createroom.impl.components_UserListView_Day_3_en","features.createroom.impl.components_UserListView_Night_3_en",0,], ["features.createroom.impl.components_UserListView_Day_4_en","features.createroom.impl.components_UserListView_Night_4_en",0,], ["features.createroom.impl.components_UserListView_Day_5_en","features.createroom.impl.components_UserListView_Night_5_en",0,], ["features.createroom.impl.components_UserListView_Day_6_en","features.createroom.impl.components_UserListView_Night_6_en",0,], -["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19951,], +["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19958,], ["features.createroom.impl.components_UserListView_Day_8_en","features.createroom.impl.components_UserListView_Night_8_en",0,], -["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19951,], +["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19958,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], ["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",0,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19951,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19951,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19951,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19951,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19951,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19951,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19951,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19951,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19951,], -["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19951,], -["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19951,], -["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19951,], -["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19951,], -["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19951,], -["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19951,], -["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19951,], -["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19951,], -["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19951,], -["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19951,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19958,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19958,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19958,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19958,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19958,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19958,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19958,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19958,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19958,], +["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19958,], +["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19958,], +["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19958,], +["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19958,], +["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19958,], +["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19958,], +["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19958,], +["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19958,], +["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19958,], +["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19958,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,], @@ -1158,12 +1158,12 @@ export const screenshots = [ ["libraries.textcomposer.components_VoiceMessageRecorderButton_Day_0_en","libraries.textcomposer.components_VoiceMessageRecorderButton_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessageRecording_Day_0_en","libraries.textcomposer.components_VoiceMessageRecording_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessage_Day_0_en","libraries.textcomposer.components_VoiceMessage_Night_0_en",0,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19951,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19951,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19951,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19951,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19951,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19958,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19958,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19958,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19958,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19958,], ["libraries.designsystem.components.media_WaveformPlaybackView_Day_0_en","libraries.designsystem.components.media_WaveformPlaybackView_Night_0_en",0,], -["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19951,], +["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19958,], ["libraries.designsystem.ruler_WithRulers_Day_0_en","libraries.designsystem.ruler_WithRulers_Night_0_en",0,], ]; diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png index a49af920d9..73cc40c167 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e09769c04ba21aba09eb0de5865f659ad092ba2e46a8b3933f95b1170b09d303 -size 28540 +oid sha256:e1c9d6912c7ad37608e5cd5511fbe4c659d14974bc36662e1ec4aa6e8ae117d5 +size 28049 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png index 4c6ae5f149..804f2f5bf1 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3702ebe296d7a14e20b3d683fb79f6b2455064a8986ce48c870b5cfd68dc5933 -size 27407 +oid sha256:b5f2274b28363382e02c53a2608f088f6865844a257956684b46db8a6557a13f +size 27028 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png index 4c6ae5f149..804f2f5bf1 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3702ebe296d7a14e20b3d683fb79f6b2455064a8986ce48c870b5cfd68dc5933 -size 27407 +oid sha256:b5f2274b28363382e02c53a2608f088f6865844a257956684b46db8a6557a13f +size 27028 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png index 1d5e048087..c1f3447d6a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b683ed9986e3fd139ee735e51a369322ba3652b2b8a578c05a61f26ee27898e0 -size 39996 +oid sha256:d3958955d2d5a0325b7c7ac2c4ca109caa1d2c7188255b9279b2e4c834a2e140 +size 39478 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png index 96ec36ca5e..0cd0ed74d5 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14d4ed02bb2f949c4cbba84933bbbfb0c550ad261695a371ef12e74a2dbd8812 -size 27600 +oid sha256:5727d595c0767a62e5658c8b7dd928a90c98507ca3d9f65742d6ade87e9e39c7 +size 27173 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png index c4e2dae54b..fc8701f05a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53f3dc9352250ba7495b6af312f3f370463291d29b76c40d4b3c340b77aa5712 -size 25455 +oid sha256:4f10c00684b08ffa30dd9d9354cf3bb45d533f553c08b80b2e910a1f2137ddf2 +size 25182 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png index c4e2dae54b..fc8701f05a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53f3dc9352250ba7495b6af312f3f370463291d29b76c40d4b3c340b77aa5712 -size 25455 +oid sha256:4f10c00684b08ffa30dd9d9354cf3bb45d533f553c08b80b2e910a1f2137ddf2 +size 25182 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png index 0fa0e6a519..845fea8138 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b380335d847fa37e5319541f46f341c5fe8016f3af48765cfe7537c59dd1f58a -size 38379 +oid sha256:d7935ebc6060c323de937690647d650932a6c0593b7eef81c277d511df325f76 +size 37919 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en.png index 6bc0eec9c0..7c39ece838 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43f2eb2cb1f1b986b58d2614c892f2f7f15f1b696a656165ba1f8644f7759476 -size 62679 +oid sha256:abf660fec7420f3f648e96fed744458f2d38d29fe09883ad4d2c4956710c549c +size 61943 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en.png index e79557dae6..910619aaaf 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08e5a9d4e1bc45e9411b74c7277f34fa0ba8d46fdd1556b65b9c50cc78f1468e -size 60595 +oid sha256:772beb3d1591eddfcca833a0f6b79bfda34c0b1bf9c3fca3808ded994353addb +size 59932 From b85e714a6fde7b0cc21185c4083f94ea6b844f17 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 11:55:20 +0000 Subject: [PATCH 171/186] Update dependency com.posthog:posthog-android to v3.5.1 --- 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 7c5f5e440c..affc0eb5db 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -186,7 +186,7 @@ zxing_cpp = "io.github.zxing-cpp:android:2.2.0" play_services_oss_licenses = "com.google.android.gms:play-services-oss-licenses:17.1.0" # Analytics -posthog = "com.posthog:posthog-android:3.5.0" +posthog = "com.posthog:posthog-android:3.5.1" sentry = "io.sentry:sentry-android:7.14.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.23.1" From c3ddf0b41e5aa816de4d7e707f065e90876d79d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 14:41:12 +0000 Subject: [PATCH 172/186] Update dependency com.android.tools:desugar_jdk_libs to v2.1.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 7c5f5e440c..4dacbb2c7c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -62,7 +62,7 @@ kover = "0.8.3" # Project android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref = "android_gradle_plugin" } # https://developer.android.com/studio/write/java8-support#library-desugaring-versions -android_desugar = "com.android.tools:desugar_jdk_libs:2.0.4" +android_desugar = "com.android.tools:desugar_jdk_libs:2.1.0" kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } kover_gradle_plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" } gms_google_services = "com.google.gms:google-services:4.4.2" From 306043876f4de997cd15d2abafdc304ebeb627ed Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 26 Aug 2024 16:50:35 +0200 Subject: [PATCH 173/186] Rename `WebPipApi` to `PipController` --- .../call/impl/pip/PictureInPictureEvents.kt | 4 ++-- .../impl/pip/PictureInPicturePresenter.kt | 20 +++++++++---------- .../features/call/impl/ui/CallScreenView.kt | 12 +++++------ .../utils/{WebPipApi.kt => PipController.kt} | 2 +- ...ewWebPipApi.kt => WebViewPipController.kt} | 4 ++-- ...{FakeWebPipApi.kt => FakePipController.kt} | 6 +++--- .../impl/pip/PictureInPicturePresenterTest.kt | 6 +++--- .../call/impl/ui/CallScreenViewTest.kt | 4 ++-- 8 files changed, 29 insertions(+), 29 deletions(-) rename features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/{WebPipApi.kt => PipController.kt} (96%) rename features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/{WebViewWebPipApi.kt => WebViewPipController.kt} (96%) rename features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/{FakeWebPipApi.kt => FakePipController.kt} (90%) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt index be376aa079..4d29f757ea 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt @@ -16,10 +16,10 @@ package io.element.android.features.call.impl.pip -import io.element.android.features.call.impl.utils.WebPipApi +import io.element.android.features.call.impl.utils.PipController sealed interface PictureInPictureEvents { - data class SetupWebPipApi(val webPipApi: WebPipApi) : PictureInPictureEvents + data class SetPipController(val pipController: PipController) : PictureInPictureEvents data object EnterPictureInPicture : PictureInPictureEvents data class OnPictureInPictureModeChanged(val isInPip: Boolean) : PictureInPictureEvents } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt index 78d347d715..e6422f2dd6 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt @@ -22,7 +22,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import io.element.android.features.call.impl.utils.WebPipApi +import io.element.android.features.call.impl.utils.PipController import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.log.logger.LoggerTag import kotlinx.coroutines.launch @@ -41,25 +41,25 @@ class PictureInPicturePresenter @Inject constructor( override fun present(): PictureInPictureState { val coroutineScope = rememberCoroutineScope() var isInPictureInPicture by remember { mutableStateOf(false) } - var webPipApi by remember { mutableStateOf(null) } + var pipController by remember { mutableStateOf(null) } fun handleEvent(event: PictureInPictureEvents) { when (event) { - is PictureInPictureEvents.SetupWebPipApi -> { - webPipApi = event.webPipApi + is PictureInPictureEvents.SetPipController -> { + pipController = event.pipController } PictureInPictureEvents.EnterPictureInPicture -> { coroutineScope.launch { - switchToPip(webPipApi) + switchToPip(pipController) } } is PictureInPictureEvents.OnPictureInPictureModeChanged -> { Timber.tag(loggerTag.value).d("onPictureInPictureModeChanged: ${event.isInPip}") isInPictureInPicture = event.isInPip if (event.isInPip) { - webPipApi?.enterPip() + pipController?.enterPip() } else { - webPipApi?.exitPip() + pipController?.exitPip() } } } @@ -85,12 +85,12 @@ class PictureInPicturePresenter @Inject constructor( /** * Enters Picture-in-Picture mode, if allowed by Element Call. */ - private suspend fun switchToPip(webPipApi: WebPipApi?) { + private suspend fun switchToPip(pipController: PipController?) { if (isPipSupported) { - if (webPipApi == null) { + if (pipController == null) { Timber.tag(loggerTag.value).w("webPipApi is not available") } - if (webPipApi == null || webPipApi.canEnterPip()) { + if (pipController == null || pipController.canEnterPip()) { Timber.tag(loggerTag.value).d("Switch to PiP mode") pipActivity?.enterPipMode() ?.also { Timber.tag(loggerTag.value).d("Switch to PiP mode result: $it") } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index e81d386dc5..5c3d02b8ac 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -40,7 +40,7 @@ import io.element.android.features.call.impl.pip.PictureInPictureEvents import io.element.android.features.call.impl.pip.PictureInPictureState import io.element.android.features.call.impl.pip.PictureInPictureStateProvider import io.element.android.features.call.impl.pip.aPictureInPictureState -import io.element.android.features.call.impl.utils.WebViewWebPipApi +import io.element.android.features.call.impl.utils.WebViewPipController import io.element.android.features.call.impl.utils.WebViewWidgetMessageInterceptor import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.ProgressDialog @@ -96,9 +96,9 @@ internal fun CallScreenView( } CallWebView( modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) - .fillMaxSize(), + .padding(padding) + .consumeWindowInsets(padding) + .fillMaxSize(), url = state.urlState, userAgent = state.userAgent, onPermissionsRequest = { request -> @@ -109,8 +109,8 @@ internal fun CallScreenView( onWebViewCreate = { webView -> val interceptor = WebViewWidgetMessageInterceptor(webView) state.eventSink(CallScreenEvents.SetupMessageChannels(interceptor)) - val webPipApi = WebViewWebPipApi(webView) - pipState.eventSink(PictureInPictureEvents.SetupWebPipApi(webPipApi)) + val pipController = WebViewPipController(webView) + pipState.eventSink(PictureInPictureEvents.SetPipController(pipController)) } ) when (state.urlState) { diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebPipApi.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/PipController.kt similarity index 96% rename from features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebPipApi.kt rename to features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/PipController.kt index af1cc6b3f9..01e23ab727 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebPipApi.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/PipController.kt @@ -16,7 +16,7 @@ package io.element.android.features.call.impl.utils -interface WebPipApi { +interface PipController { suspend fun canEnterPip(): Boolean fun enterPip() fun exitPip() diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewPipController.kt similarity index 96% rename from features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt rename to features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewPipController.kt index baf682d6b3..2a90965c8c 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWebPipApi.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewPipController.kt @@ -20,9 +20,9 @@ import android.webkit.WebView import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine -class WebViewWebPipApi( +class WebViewPipController( private val webView: WebView, -) : WebPipApi { +) : PipController { override suspend fun canEnterPip(): Boolean { return suspendCoroutine { continuation -> webView.evaluateJavascript("controls.canEnterPip()") { result -> diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakeWebPipApi.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipController.kt similarity index 90% rename from features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakeWebPipApi.kt rename to features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipController.kt index ca752cd8ce..086feecd39 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakeWebPipApi.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipController.kt @@ -16,14 +16,14 @@ package io.element.android.features.call.impl.pip -import io.element.android.features.call.impl.utils.WebPipApi +import io.element.android.features.call.impl.utils.PipController import io.element.android.tests.testutils.lambda.lambdaError -class FakeWebPipApi( +class FakePipController( private val canEnterPipResult: () -> Boolean = { lambdaError() }, private val enterPipResult: () -> Unit = { lambdaError() }, private val exitPipResult: () -> Unit = { lambdaError() }, -) : WebPipApi { +) : PipController { override suspend fun canEnterPip(): Boolean = canEnterPipResult() override fun enterPip() = enterPipResult() diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt index 2343f2cb70..a5fb1f8beb 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt @@ -92,7 +92,7 @@ class PictureInPicturePresenterTest { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(PictureInPictureEvents.SetupWebPipApi(FakeWebPipApi(canEnterPipResult = { false }))) + initialState.eventSink(PictureInPictureEvents.SetPipController(FakePipController(canEnterPipResult = { false }))) initialState.eventSink(PictureInPictureEvents.EnterPictureInPicture) handUpResult.assertions().isCalledOnce() } @@ -115,8 +115,8 @@ class PictureInPicturePresenterTest { }.test { val initialState = awaitItem() initialState.eventSink( - PictureInPictureEvents.SetupWebPipApi( - FakeWebPipApi( + PictureInPictureEvents.SetPipController( + FakePipController( canEnterPipResult = { true }, enterPipResult = enterPipResult, exitPipResult = exitPipResult, diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/ui/CallScreenViewTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/ui/CallScreenViewTest.kt index e92e9cc4e6..ec75b9a1fa 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/ui/CallScreenViewTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/ui/CallScreenViewTest.kt @@ -52,7 +52,7 @@ class CallScreenViewTest { eventsRecorder.assertTrue(0) { it is CallScreenEvents.SetupMessageChannels } eventsRecorder.assertTrue(1) { it == CallScreenEvents.Hangup } pipEventsRecorder.assertSize(1) - pipEventsRecorder.assertTrue(0) { it is PictureInPictureEvents.SetupWebPipApi } + pipEventsRecorder.assertTrue(0) { it is PictureInPictureEvents.SetPipController } } @Test @@ -72,7 +72,7 @@ class CallScreenViewTest { eventsRecorder.assertSize(1) eventsRecorder.assertTrue(0) { it is CallScreenEvents.SetupMessageChannels } pipEventsRecorder.assertSize(2) - pipEventsRecorder.assertTrue(0) { it is PictureInPictureEvents.SetupWebPipApi } + pipEventsRecorder.assertTrue(0) { it is PictureInPictureEvents.SetPipController } pipEventsRecorder.assertTrue(1) { it == PictureInPictureEvents.EnterPictureInPicture } } } From 9fab13c50be261f7da406188a4950b6a245381f5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 26 Aug 2024 17:11:41 +0200 Subject: [PATCH 174/186] Avoid keeping a reference to the eventSink in a separate value --- .../call/impl/ui/ElementCallActivity.kt | 52 +++++++++++++------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt index 8c758c2ee5..abeafad4d3 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt @@ -33,14 +33,21 @@ import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.rememberUpdatedState +import androidx.core.app.PictureInPictureModeChangedInfo import androidx.core.content.IntentCompat +import androidx.core.util.Consumer import androidx.lifecycle.Lifecycle import io.element.android.features.call.api.CallType import io.element.android.features.call.impl.DefaultElementCallEntryPoint import io.element.android.features.call.impl.di.CallBindings import io.element.android.features.call.impl.pip.PictureInPictureEvents import io.element.android.features.call.impl.pip.PictureInPicturePresenter +import io.element.android.features.call.impl.pip.PictureInPictureState import io.element.android.features.call.impl.pip.PipActivity import io.element.android.features.call.impl.services.CallForegroundService import io.element.android.features.call.impl.utils.CallIntentDataParser @@ -74,7 +81,6 @@ class ElementCallActivity : private val webViewTarget = mutableStateOf(null) private var eventSink: ((CallScreenEvents) -> Unit)? = null - private var pipEventSink: ((PictureInPictureEvents) -> Unit)? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -102,7 +108,7 @@ class ElementCallActivity : setContent { val pipState = pictureInPicturePresenter.present() - pipEventSink = pipState.eventSink + ListenToAndroidEvents(pipState) ElementThemeApp(appPreferencesStore) { val state = presenter.present() eventSink = state.eventSink @@ -118,21 +124,38 @@ class ElementCallActivity : } } + @Composable + private fun ListenToAndroidEvents(pipState: PictureInPictureState) { + val pipEventSink by rememberUpdatedState(pipState.eventSink) + DisposableEffect(Unit) { + val onUserLeaveHintListener = Runnable { + pipEventSink(PictureInPictureEvents.EnterPictureInPicture) + } + addOnUserLeaveHintListener(onUserLeaveHintListener) + onDispose { + removeOnUserLeaveHintListener(onUserLeaveHintListener) + } + } + DisposableEffect(Unit) { + val onPictureInPictureModeChangedListener = Consumer { _: PictureInPictureModeChangedInfo -> + pipEventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(isInPictureInPictureMode)) + if (!isInPictureInPictureMode && !lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { + Timber.d("Exiting PiP mode: Hangup the call") + eventSink?.invoke(CallScreenEvents.Hangup) + } + } + addOnPictureInPictureModeChangedListener(onPictureInPictureModeChangedListener) + onDispose { + removeOnPictureInPictureModeChangedListener(onPictureInPictureModeChangedListener) + } + } + } + override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) updateUiMode(newConfig) } - override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) { - super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig) - pipEventSink?.invoke(PictureInPictureEvents.OnPictureInPictureModeChanged(isInPictureInPictureMode)) - - if (!isInPictureInPictureMode && !lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { - Timber.d("Exiting PiP mode: Hangup the call") - eventSink?.invoke(CallScreenEvents.Hangup) - } - } - override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) setCallType(intent) @@ -150,11 +173,6 @@ class ElementCallActivity : } } - override fun onUserLeaveHint() { - super.onUserLeaveHint() - pipEventSink?.invoke(PictureInPictureEvents.EnterPictureInPicture) - } - override fun onDestroy() { super.onDestroy() releaseAudioFocus() From 7f4b84638f2591093b4fd2a0cfca35420765a673 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 26 Aug 2024 17:15:32 +0200 Subject: [PATCH 175/186] Rename `PipActivity` to `PipView` --- .../call/impl/pip/PictureInPicturePresenter.kt | 14 +++++++------- .../call/impl/pip/{PipActivity.kt => PipView.kt} | 2 +- .../features/call/impl/ui/ElementCallActivity.kt | 8 ++++---- .../pip/{FakePipActivity.kt => FakePipView.kt} | 4 ++-- .../call/impl/pip/PictureInPicturePresenterTest.kt | 14 +++++++------- 5 files changed, 21 insertions(+), 21 deletions(-) rename features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/{PipActivity.kt => PipView.kt} (96%) rename features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/{FakePipActivity.kt => FakePipView.kt} (96%) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt index e6422f2dd6..ab0b8f49b9 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt @@ -35,7 +35,7 @@ class PictureInPicturePresenter @Inject constructor( pipSupportProvider: PipSupportProvider, ) : Presenter { private val isPipSupported = pipSupportProvider.isPipSupported() - private var pipActivity: PipActivity? = null + private var pipView: PipView? = null @Composable override fun present(): PictureInPictureState { @@ -72,13 +72,13 @@ class PictureInPicturePresenter @Inject constructor( ) } - fun setPipActivity(pipActivity: PipActivity?) { + fun setPipView(pipView: PipView?) { if (isPipSupported) { Timber.tag(loggerTag.value).d("Setting PiP params") - this.pipActivity = pipActivity - pipActivity?.setPipParams() + this.pipView = pipView + pipView?.setPipParams() } else { - Timber.tag(loggerTag.value).d("onCreate: PiP is not supported") + Timber.tag(loggerTag.value).d("setPipView: PiP is not supported") } } @@ -92,11 +92,11 @@ class PictureInPicturePresenter @Inject constructor( } if (pipController == null || pipController.canEnterPip()) { Timber.tag(loggerTag.value).d("Switch to PiP mode") - pipActivity?.enterPipMode() + pipView?.enterPipMode() ?.also { Timber.tag(loggerTag.value).d("Switch to PiP mode result: $it") } } else { Timber.tag(loggerTag.value).w("Cannot enter PiP mode, hangup the call") - pipActivity?.hangUp() + pipView?.hangUp() } } } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipView.kt similarity index 96% rename from features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipActivity.kt rename to features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipView.kt index 6b86988ae2..998d36da5c 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipActivity.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipView.kt @@ -16,7 +16,7 @@ package io.element.android.features.call.impl.pip -interface PipActivity { +interface PipView { fun setPipParams() fun enterPipMode(): Boolean fun hangUp() diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt index abeafad4d3..2ae53d571f 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt @@ -48,7 +48,7 @@ import io.element.android.features.call.impl.di.CallBindings import io.element.android.features.call.impl.pip.PictureInPictureEvents import io.element.android.features.call.impl.pip.PictureInPicturePresenter import io.element.android.features.call.impl.pip.PictureInPictureState -import io.element.android.features.call.impl.pip.PipActivity +import io.element.android.features.call.impl.pip.PipView import io.element.android.features.call.impl.services.CallForegroundService import io.element.android.features.call.impl.utils.CallIntentDataParser import io.element.android.libraries.architecture.bindings @@ -60,7 +60,7 @@ import javax.inject.Inject class ElementCallActivity : AppCompatActivity(), CallScreenNavigator, - PipActivity { + PipView { @Inject lateinit var callIntentDataParser: CallIntentDataParser @Inject lateinit var presenterFactory: CallScreenPresenter.Factory @Inject lateinit var appPreferencesStore: AppPreferencesStore @@ -101,7 +101,7 @@ class ElementCallActivity : updateUiMode(resources.configuration) } - pictureInPicturePresenter.setPipActivity(this) + pictureInPicturePresenter.setPipView(this) audioManager = getSystemService(AUDIO_SERVICE) as AudioManager requestAudioFocus() @@ -177,7 +177,7 @@ class ElementCallActivity : super.onDestroy() releaseAudioFocus() CallForegroundService.stop(this) - pictureInPicturePresenter.setPipActivity(null) + pictureInPicturePresenter.setPipView(null) } override fun finish() { diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipActivity.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipView.kt similarity index 96% rename from features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipActivity.kt rename to features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipView.kt index 8a3089453e..d07eb52c90 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipActivity.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/FakePipView.kt @@ -18,11 +18,11 @@ package io.element.android.features.call.impl.pip import io.element.android.tests.testutils.lambda.lambdaError -class FakePipActivity( +class FakePipView( private val setPipParamsResult: () -> Unit = { lambdaError() }, private val enterPipModeResult: () -> Boolean = { lambdaError() }, private val handUpResult: () -> Unit = { lambdaError() } -) : PipActivity { +) : PipView { override fun setPipParams() = setPipParamsResult() override fun enterPipMode(): Boolean = enterPipModeResult() override fun hangUp() = handUpResult() diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt index a5fb1f8beb..e433a09378 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt @@ -34,14 +34,14 @@ class PictureInPicturePresenterTest { val initialState = awaitItem() assertThat(initialState.supportPip).isFalse() } - presenter.setPipActivity(null) + presenter.setPipView(null) } @Test fun `when pip is supported, the state value supportPip is true`() = runTest { val presenter = createPictureInPicturePresenter( supportPip = true, - pipActivity = FakePipActivity(setPipParamsResult = { }), + pipView = FakePipView(setPipParamsResult = { }), ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -56,7 +56,7 @@ class PictureInPicturePresenterTest { val enterPipModeResult = lambdaRecorder { true } val presenter = createPictureInPicturePresenter( supportPip = true, - pipActivity = FakePipActivity( + pipView = FakePipView( setPipParamsResult = { }, enterPipModeResult = enterPipModeResult, ), @@ -83,7 +83,7 @@ class PictureInPicturePresenterTest { val handUpResult = lambdaRecorder { } val presenter = createPictureInPicturePresenter( supportPip = true, - pipActivity = FakePipActivity( + pipView = FakePipView( setPipParamsResult = { }, handUpResult = handUpResult ), @@ -105,7 +105,7 @@ class PictureInPicturePresenterTest { val exitPipResult = lambdaRecorder { } val presenter = createPictureInPicturePresenter( supportPip = true, - pipActivity = FakePipActivity( + pipView = FakePipView( setPipParamsResult = { }, enterPipModeResult = enterPipModeResult ), @@ -141,12 +141,12 @@ class PictureInPicturePresenterTest { private fun createPictureInPicturePresenter( supportPip: Boolean = true, - pipActivity: PipActivity? = FakePipActivity() + pipView: PipView? = FakePipView() ): PictureInPicturePresenter { return PictureInPicturePresenter( pipSupportProvider = FakePipSupportProvider(supportPip), ).apply { - setPipActivity(pipActivity) + setPipView(pipView) } } } From 4e887388ae983fa3aeecde9ff644226b9456dcef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:57:05 +0000 Subject: [PATCH 176/186] Update dependency org.matrix.rustcomponents:sdk-android to v0.2.40 --- 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 2f5294ae10..a9bc7ec95b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.39" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.40" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From dea05679c7d21ca65f4184803df88f56b5698c12 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:57:13 +0000 Subject: [PATCH 177/186] Update media3 to v1.4.1 --- 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 2f5294ae10..031093e462 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,7 @@ constraintlayout = "2.1.4" constraintlayout_compose = "1.0.1" lifecycle = "2.8.4" activity = "1.9.1" -media3 = "1.4.0" +media3 = "1.4.1" camera = "1.3.4" # Compose From e5b21c389e5a67a2eb5c133e4821eea2eac68523 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 27 Aug 2024 17:42:00 +0200 Subject: [PATCH 178/186] Rust sdk : use newMessageShield state --- .../messages/impl/timeline/components/MessageShieldView.kt | 7 ++++++- .../matrix/api/timeline/item/event/MessageShield.kt | 4 ++++ .../impl/timeline/item/event/EventTimelineItemMapper.kt | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt index 73d4c9ba88..9f9dc0ba05 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt @@ -88,6 +88,7 @@ internal fun MessageShield.toText(): String { is MessageShield.UnsignedDevice -> CommonStrings.event_shield_reason_unsigned_device is MessageShield.UnverifiedIdentity -> CommonStrings.event_shield_reason_unverified_identity is MessageShield.SentInClear -> CommonStrings.event_shield_reason_sent_in_clear + is MessageShield.PreviouslyVerified -> CommonStrings.event_shield_reason_previously_verified } ) } @@ -98,7 +99,8 @@ internal fun MessageShield.toIcon(): ImageVector { is MessageShield.AuthenticityNotGuaranteed -> CompoundIcons.Info() is MessageShield.UnknownDevice, is MessageShield.UnsignedDevice, - is MessageShield.UnverifiedIdentity -> CompoundIcons.HelpSolid() + is MessageShield.UnverifiedIdentity, + is MessageShield.PreviouslyVerified -> CompoundIcons.HelpSolid() is MessageShield.SentInClear -> CompoundIcons.LockOff() } } @@ -126,6 +128,9 @@ internal fun MessageShieldViewPreview() { MessageShieldView( shield = MessageShield.SentInClear(false) ) + MessageShieldView( + shield = MessageShield.PreviouslyVerified(false) + ) } } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt index 9092817569..140df16d66 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageShield.kt @@ -34,6 +34,9 @@ sealed interface MessageShield { /** An unencrypted event in an encrypted room. */ data class SentInClear(val isCritical: Boolean) : MessageShield + + /** The sender was previously verified but changed their identity. */ + data class PreviouslyVerified(val isCritical: Boolean) : MessageShield } val MessageShield.isCritical: Boolean @@ -43,4 +46,5 @@ val MessageShield.isCritical: Boolean is MessageShield.UnsignedDevice -> isCritical is MessageShield.UnverifiedIdentity -> isCritical is MessageShield.SentInClear -> isCritical + is MessageShield.PreviouslyVerified -> isCritical } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt index 523b8e1fb5..8a155b2826 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt @@ -152,5 +152,6 @@ private fun ShieldState?.map(): MessageShield? { ShieldStateCode.UNSIGNED_DEVICE -> MessageShield.UnsignedDevice(isCritical) ShieldStateCode.UNVERIFIED_IDENTITY -> MessageShield.UnverifiedIdentity(isCritical) ShieldStateCode.SENT_IN_CLEAR -> MessageShield.SentInClear(isCritical) + ShieldStateCode.PREVIOUSLY_VERIFIED -> MessageShield.PreviouslyVerified(isCritical) } } From 88a581427c9bf0f84ae3f6e9a0c4c8bc5aa2e14c Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 27 Aug 2024 17:45:22 +0200 Subject: [PATCH 179/186] Rust sdk : refactor LocalSendState to use the new failure states as iOS does --- .../impl/timeline/TimelineStateProvider.kt | 4 +-- .../components/TimelineEventTimestampView.kt | 6 ++-- ...melineItemEventForTimestampViewProvider.kt | 8 ++--- ...iewStateForTimelineItemEventRowProvider.kt | 2 +- .../receipt/ReadReceiptViewStateProvider.kt | 2 +- .../receipt/TimelineItemReadReceiptView.kt | 33 +++++++++---------- .../impl/timeline/model/TimelineItem.kt | 2 +- .../item/event/LocalEventSendState.kt | 22 ++++++++++--- .../item/event/EventTimelineItemMapper.kt | 16 ++++++--- 9 files changed, 57 insertions(+), 38 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 677989a81a..f1abc52725 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -84,7 +84,7 @@ internal fun aTimelineItemList(content: TimelineItemEventContent): ImmutableList isMine = false, content = content, groupPosition = TimelineItemGroupPosition.Middle, - sendState = LocalEventSendState.SendingFailed.Unrecoverable("Message failed to send"), + sendState = LocalEventSendState.Failed.Unknown("Message failed to send"), ), aTimelineItemEvent( isMine = false, @@ -107,7 +107,7 @@ internal fun aTimelineItemList(content: TimelineItemEventContent): ImmutableList isMine = true, content = content, groupPosition = TimelineItemGroupPosition.Middle, - sendState = LocalEventSendState.SendingFailed.Unrecoverable("Message failed to send"), + sendState = LocalEventSendState.Failed.Unknown("Message failed to send"), ), aTimelineItemEvent( isMine = true, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt index 69c2a807a2..86781e5c87 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt @@ -51,10 +51,10 @@ fun TimelineEventTimestampView( modifier: Modifier = Modifier, ) { val formattedTime = event.sentTime - val hasUnrecoverableError = event.localSendState is LocalEventSendState.SendingFailed.Unrecoverable + val hasError = event.localSendState is LocalEventSendState.Failed val hasEncryptionCritical = event.messageShield?.isCritical.orFalse() val isMessageEdited = event.content.isEdited() - val tint = if (hasUnrecoverableError || hasEncryptionCritical) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.secondary + val tint = if (hasError || hasEncryptionCritical) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.secondary Row( modifier = Modifier .padding(PaddingValues(start = TimelineEventTimestampViewDefaults.spacing)) @@ -74,7 +74,7 @@ fun TimelineEventTimestampView( style = ElementTheme.typography.fontBodyXsRegular, color = tint, ) - if (hasUnrecoverableError) { + if (hasError) { Spacer(modifier = Modifier.width(2.dp)) Icon( imageVector = CompoundIcons.Error(), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventForTimestampViewProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventForTimestampViewProvider.kt index 705ac36df5..b7237720bd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventForTimestampViewProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventForTimestampViewProvider.kt @@ -27,15 +27,13 @@ class TimelineItemEventForTimestampViewProvider : PreviewParameterProvider get() = sequenceOf( aTimelineItemEvent(), - // Sending failed recoverable - aTimelineItemEvent().copy(localSendState = LocalEventSendState.SendingFailed.Recoverable("AN_ERROR")), - // Sending failed unrecoverable - aTimelineItemEvent().copy(localSendState = LocalEventSendState.SendingFailed.Unrecoverable("AN_ERROR")), + aTimelineItemEvent().copy(localSendState = LocalEventSendState.Sending), + aTimelineItemEvent().copy(localSendState = LocalEventSendState.Failed.Unknown("AN_ERROR")), // Edited aTimelineItemEvent().copy(content = aTimelineItemTextContent().copy(isEdited = true)), // Sending failed + Edited (not sure this is possible IRL, but should be covered by test) aTimelineItemEvent().copy( - localSendState = LocalEventSendState.SendingFailed.Unrecoverable("AN_ERROR"), + localSendState = LocalEventSendState.Failed.Unknown("AN_ERROR"), content = aTimelineItemTextContent().copy(isEdited = true), ), aTimelineItemEvent().copy( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateForTimelineItemEventRowProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateForTimelineItemEventRowProvider.kt index 1595e59f54..20bca9fbd7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateForTimelineItemEventRowProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateForTimelineItemEventRowProvider.kt @@ -26,7 +26,7 @@ class ReadReceiptViewStateForTimelineItemEventRowProvider : override val values: Sequence get() = sequenceOf( aReadReceiptViewState( - sendState = LocalEventSendState.NotSentYet + sendState = LocalEventSendState.Sending, ), aReadReceiptViewState( sendState = LocalEventSendState.Sent(EventId("\$eventId")), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateProvider.kt index a40e94c529..6288919abe 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateProvider.kt @@ -29,7 +29,7 @@ class ReadReceiptViewStateProvider : PreviewParameterProvider get() = sequenceOf( aReadReceiptViewState(), - aReadReceiptViewState(sendState = LocalEventSendState.NotSentYet), + aReadReceiptViewState(sendState = LocalEventSendState.Sending), aReadReceiptViewState(sendState = LocalEventSendState.Sent(EventId("\$eventId"))), aReadReceiptViewState( sendState = LocalEventSendState.Sent(EventId("\$eventId")), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt index 0342f684dd..d8cdcbe05f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt @@ -70,19 +70,18 @@ fun TimelineItemReadReceiptView( ReadReceiptsAvatars( receipts = state.receipts, modifier = Modifier - .testTag(TestTags.messageReadReceipts) - .clip(RoundedCornerShape(4.dp)) - .clickable { - onReadReceiptsClick() - } - .padding(2.dp) + .testTag(TestTags.messageReadReceipts) + .clip(RoundedCornerShape(4.dp)) + .clickable { + onReadReceiptsClick() + } + .padding(2.dp) ) } } } else { when (state.sendState) { - LocalEventSendState.NotSentYet, - is LocalEventSendState.SendingFailed.Recoverable -> { + LocalEventSendState.Sending -> { ReadReceiptsRow(modifier) { Icon( modifier = Modifier.padding(2.dp), @@ -92,7 +91,7 @@ fun TimelineItemReadReceiptView( ) } } - is LocalEventSendState.SendingFailed.Unrecoverable -> { + is LocalEventSendState.Failed -> { // Error? The timestamp is already displayed in red } null, @@ -119,9 +118,9 @@ private fun ReadReceiptsRow( ) { Row( modifier = modifier - .fillMaxWidth() - .height(AvatarSize.TimelineReadReceipt.dp + 8.dp) - .padding(horizontal = 18.dp), + .fillMaxWidth() + .height(AvatarSize.TimelineReadReceipt.dp + 8.dp) + .padding(horizontal = 18.dp), horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, ) { @@ -160,11 +159,11 @@ private fun ReadReceiptsAvatars( .forEachIndexed { index, readReceiptData -> Box( modifier = Modifier - .padding(end = (12.dp + avatarStrokeSize * 2) * index) - .size(size = avatarSize + avatarStrokeSize * 2) - .clip(CircleShape) - .background(avatarStrokeColor) - .zIndex(index.toFloat()), + .padding(end = (12.dp + avatarStrokeSize * 2) * index) + .size(size = avatarSize + avatarStrokeSize * 2) + .clip(CircleShape) + .background(avatarStrokeColor) + .zIndex(index.toFloat()), contentAlignment = Alignment.Center, ) { Avatar( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt index 208a6b07dc..2cb872e95f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt @@ -90,7 +90,7 @@ sealed interface TimelineItem { val safeSenderName: String = senderProfile.getDisambiguatedDisplayName(senderId) - val failedToSend: Boolean = localSendState is LocalEventSendState.SendingFailed + val failedToSend: Boolean = localSendState is LocalEventSendState.Failed val isTextMessage: Boolean = content is TimelineItemTextBasedContent diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/LocalEventSendState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/LocalEventSendState.kt index b956e51168..8e5f539d81 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/LocalEventSendState.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/LocalEventSendState.kt @@ -18,13 +18,27 @@ package io.element.android.libraries.matrix.api.timeline.item.event import androidx.compose.runtime.Immutable import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UserId @Immutable sealed interface LocalEventSendState { - data object NotSentYet : LocalEventSendState - sealed class SendingFailed(open val error: String) : LocalEventSendState { - data class Recoverable(override val error: String) : SendingFailed(error) - data class Unrecoverable(override val error: String) : SendingFailed(error) + data object Sending : LocalEventSendState + sealed interface Failed : LocalEventSendState { + data class Unknown(val error: String) : Failed + data class VerifiedUserHasUnsignedDevice( + /** + * The unsigned devices belonging to verified users. A map from user ID + * to a list of device IDs. + */ + val devices: Map> + ) : Failed + + data class VerifiedUserChangedIdentity( + /** + * The users that were previously verified but are no longer. + */ + val users: List + ) : Failed } data class Sent( val eventId: EventId diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt index 8a155b2826..d51e4bf3c8 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt @@ -81,15 +81,23 @@ fun RustProfileDetails.map(): ProfileTimelineDetails { fun RustEventSendState?.map(): LocalEventSendState? { return when (this) { null -> null - RustEventSendState.NotSentYet -> LocalEventSendState.NotSentYet + RustEventSendState.NotSentYet -> LocalEventSendState.Sending is RustEventSendState.SendingFailed -> { - if (this.isRecoverable) { - LocalEventSendState.SendingFailed.Recoverable(this.error) + if (isRecoverable) { + LocalEventSendState.Sending } else { - LocalEventSendState.SendingFailed.Unrecoverable(this.error) + LocalEventSendState.Failed.Unknown(error) } } is RustEventSendState.Sent -> LocalEventSendState.Sent(EventId(eventId)) + is RustEventSendState.VerifiedUserChangedIdentity -> { + LocalEventSendState.Failed.VerifiedUserChangedIdentity(users.map { UserId(it) }) + } + is RustEventSendState.VerifiedUserHasUnsignedDevice -> { + LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice( + devices = devices.mapKeys { UserId(it.key) } + ) + } } } From 2361b597d96b88786c95e7489139a67a802f5e89 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 27 Aug 2024 17:45:32 +0200 Subject: [PATCH 180/186] Rust sdk : handle the remaining changes --- .../libraries/matrix/api/notification/NotificationData.kt | 7 ++++++- .../libraries/matrix/impl/RustMatrixClientFactory.kt | 3 ++- .../TimelineEventToNotificationContentMapper.kt | 2 +- .../libraries/matrix/impl/room/MatrixRoomInfoMapper.kt | 2 +- .../matrix/impl/roomlist/RoomSummaryDetailsFactory.kt | 2 +- .../impl/notifications/DefaultNotifiableEventResolver.kt | 2 +- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt index 1696375bcb..74bd2d8e14 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt @@ -53,6 +53,7 @@ sealed interface NotificationContent { data class CallInvite( val senderId: UserId, ) : MessageLike + data class CallNotify( val senderId: UserId, val type: CallNotifyType, @@ -77,7 +78,11 @@ sealed interface NotificationContent { val messageType: MessageType ) : MessageLike - data object RoomRedaction : MessageLike + data class RoomRedaction( + val redactedEventId: String?, + val reason: String? + ) : MessageLike + data object Sticker : MessageLike data class Poll( val senderId: UserId, 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 51e71f3855..a3304dc5bf 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 @@ -93,7 +93,8 @@ class RustMatrixClientFactory @Inject constructor( slidingSync: ClientBuilderSlidingSync, ): ClientBuilder { return ClientBuilder() - .sessionPath(sessionPath) + // TODO SDK claims it's valid to use the same path for data and cache, but would be better to use different paths + .sessionPaths(dataPath = sessionPath, cachePath = sessionPath) .passphrase(passphrase) .slidingSyncProxy(slidingSyncProxy) .userAgent(userAgentProvider.provide()) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt index 4591a2ef52..fa0b6365f3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt @@ -94,7 +94,7 @@ private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationCon is MessageLikeEventContent.RoomMessage -> { NotificationContent.MessageLike.RoomMessage(senderId, EventMessageMapper().mapMessageType(messageType)) } - MessageLikeEventContent.RoomRedaction -> NotificationContent.MessageLike.RoomRedaction + is MessageLikeEventContent.RoomRedaction -> NotificationContent.MessageLike.RoomRedaction(redactedEventId = redactedEventId, reason = reason) MessageLikeEventContent.Sticker -> NotificationContent.MessageLike.Sticker is MessageLikeEventContent.Poll -> NotificationContent.MessageLike.Poll(senderId, question) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt index a7461d6b0a..b53b7629fd 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt @@ -56,7 +56,7 @@ class MatrixRoomInfoMapper { userPowerLevels = mapPowerLevels(it.userPowerLevels), highlightCount = it.highlightCount.toLong(), notificationCount = it.notificationCount.toLong(), - userDefinedNotificationMode = it.userDefinedNotificationMode?.map(), + userDefinedNotificationMode = it.cachedUserDefinedNotificationMode?.map(), hasRoomCall = it.hasRoomCall, activeRoomCallParticipants = it.activeRoomCallParticipants.toImmutableList(), heroes = it.elementHeroes().toImmutableList(), diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt index 9c67eb1221..8f0863ec2c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt @@ -47,7 +47,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto isMarkedUnread = roomInfo.isMarkedUnread, lastMessage = latestRoomMessage, inviter = roomInfo.inviter?.let(RoomMemberMapper::map), - userDefinedNotificationMode = roomInfo.userDefinedNotificationMode?.let(RoomNotificationSettingsMapper::mapMode), + userDefinedNotificationMode = roomInfo.cachedUserDefinedNotificationMode?.let(RoomNotificationSettingsMapper::mapMode), hasRoomCall = roomInfo.hasRoomCall, isDm = isDm(isDirect = roomInfo.isDirect, activeMembersCount = roomInfo.activeMembersCount.toInt()), isFavorite = roomInfo.isFavourite, 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 953215feb2..ef97dbf002 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 @@ -204,7 +204,7 @@ class DefaultNotifiableEventResolver @Inject constructor( NotificationContent.MessageLike.RoomEncrypted -> fallbackNotifiableEvent(userId, roomId, eventId).also { Timber.tag(loggerTag.value).w("Notification with encrypted content -> fallback") } - NotificationContent.MessageLike.RoomRedaction -> null.also { + is NotificationContent.MessageLike.RoomRedaction -> null.also { Timber.tag(loggerTag.value).d("Ignoring notification for redaction") } NotificationContent.MessageLike.Sticker -> null.also { From 2aa49d40a4d565eb1f7cc2f801af7b89363000c1 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 27 Aug 2024 15:55:18 +0000 Subject: [PATCH 181/186] Update screenshots --- ...es.impl.timeline.components_MessageShieldView_Day_0_en.png | 4 ++-- ....impl.timeline.components_MessageShieldView_Night_0_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png index aa89a718dc..4a3994d148 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:18808ed71ef0cbc10be0eda977ab077a0eaa83afbfd2ae50c500b802aa4c7976 -size 30901 +oid sha256:df2ef6fe59cddc72475c85750cf76384056152c8271bc480748fde31e7d2ef13 +size 36201 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png index 9b49043ac6..d60d1bd163 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_MessageShieldView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d0ad0c7f690d07d67a13fcad3ee8901a77602affe063d2f8222345de3aff934 -size 30039 +oid sha256:a1ed76be54d00c0290b315b2322288d5bce83834c8b382b11b83bc4f82bb9cdc +size 35103 From ad646c90980ee2637230e3ac6a8e9f56e790fd8b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Aug 2024 18:41:40 +0200 Subject: [PATCH 182/186] Remove feature flag `PictureInPicture` --- .../features/call/impl/pip/PipSupportProvider.kt | 10 +--------- .../android/libraries/featureflag/api/FeatureFlags.kt | 7 ------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipSupportProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipSupportProvider.kt index 6cf3f080ad..3762174481 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipSupportProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PipSupportProvider.kt @@ -24,9 +24,6 @@ import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.ApplicationContext -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import kotlinx.coroutines.runBlocking import javax.inject.Inject interface PipSupportProvider { @@ -37,15 +34,10 @@ interface PipSupportProvider { @ContributesBinding(AppScope::class) class DefaultPipSupportProvider @Inject constructor( @ApplicationContext private val context: Context, - private val featureFlagService: FeatureFlagService, ) : PipSupportProvider { override fun isPipSupported(): Boolean { val isSupportedByTheOs = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && context.packageManager?.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE).orFalse() - return if (isSupportedByTheOs) { - runBlocking { featureFlagService.isFeatureEnabled(FeatureFlags.PictureInPicture) } - } else { - false - } + return isSupportedByTheOs } } diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 93951003f8..971d99c095 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -120,13 +120,6 @@ enum class FeatureFlags( defaultValue = { true }, isFinished = false, ), - PictureInPicture( - key = "feature.pictureInPicture", - title = "Picture in Picture for Calls", - description = "Allow the Call to be rendered in PiP mode", - defaultValue = { it.buildType != BuildType.RELEASE }, - isFinished = false, - ), PinnedEvents( key = "feature.pinnedEvents", title = "Pinned Events", From 7310adcf079656a8a4996c430e923d29e28a8da8 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 27 Aug 2024 20:46:15 +0200 Subject: [PATCH 183/186] Rust sdk : fix tests after api breaks --- .../matrix/impl/roomlist/RoomSummaryListProcessorTest.kt | 2 +- .../impl/notifications/DefaultNotifiableEventResolverTest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 abaae99397..5458c2dd1a 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 @@ -246,7 +246,7 @@ private fun aRustRoomInfo( userPowerLevels = userPowerLevels, highlightCount = highlightCount, notificationCount = notificationCount, - userDefinedNotificationMode = userDefinedNotificationMode, + cachedUserDefinedNotificationMode = userDefinedNotificationMode, hasRoomCall = hasRoomCall, activeRoomCallParticipants = activeRoomCallParticipants, isMarkedUnread = isMarkedUnread, diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt index 0fa3f730aa..0c0dbcc495 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt @@ -598,7 +598,7 @@ class DefaultNotifiableEventResolverTest { testNull(NotificationContent.MessageLike.KeyVerificationMac) testNull(NotificationContent.MessageLike.KeyVerificationDone) testNull(NotificationContent.MessageLike.ReactionContent(relatedEventId = AN_EVENT_ID_2.value)) - testNull(NotificationContent.MessageLike.RoomRedaction) + testNull(NotificationContent.MessageLike.RoomRedaction(redactedEventId = AN_EVENT_ID_2.value, reason = null)) testNull(NotificationContent.MessageLike.Sticker) testNull(NotificationContent.StateEvent.PolicyRuleRoom) testNull(NotificationContent.StateEvent.PolicyRuleServer) From aa1802c1197dafd8e46b38868fc5405070a6a8e6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 21:58:17 +0000 Subject: [PATCH 184/186] Update dependencyAnalysis to v2 --- 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 2f5294ae10..a368a184f3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ test_core = "1.6.1" #other coil = "2.7.0" datetime = "0.6.0" -dependencyAnalysis = "1.33.0" +dependencyAnalysis = "2.0.0" serialization_json = "1.6.3" showkase = "1.0.3" appyx = "1.4.0" From efea19b475ca26c1f08b00323ad46b69f8a093f5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 04:35:29 +0000 Subject: [PATCH 185/186] Update dependency org.maplibre.gl:android-sdk to v11.2.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 2f5294ae10..00d67be551 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -177,7 +177,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:11.1.0" +maplibre = "org.maplibre.gl:android-sdk:11.2.0" maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.0" maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.0" opusencoder = "io.element.android:opusencoder:1.1.0" From e2275816bf5d2f142e5cf92afea36a5f14017f64 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 28 Aug 2024 12:11:55 +0200 Subject: [PATCH 186/186] Adding fastlane file for version 0.5.1 --- fastlane/metadata/android/en-US/changelogs/40005010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40005010.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40005010.txt b/fastlane/metadata/android/en-US/changelogs/40005010.txt new file mode 100644 index 0000000000..3c6c01983c --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40005010.txt @@ -0,0 +1,2 @@ +Main changes in this version: Element Call improvements and bug fixes. +Full changelog: https://github.com/element-hq/element-x-android/releases \ No newline at end of file