From 5313f35b0606d36345e54197e276adb04c021315 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 9 Sep 2025 14:46:07 +0200 Subject: [PATCH 001/145] Remove unused onLogoutForNativeSlidingSyncMigrationNeeded() method and cleanup dead code. --- .../android/appnav/LoggedInFlowNode.kt | 20 ------------------- .../features/home/api/HomeEntryPoint.kt | 1 - 2 files changed, 21 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index 2d08d5f6f5..82f9dcb9b6 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -52,7 +52,6 @@ import io.element.android.features.ftue.api.FtueEntryPoint import io.element.android.features.ftue.api.state.FtueService import io.element.android.features.ftue.api.state.FtueState import io.element.android.features.home.api.HomeEntryPoint -import io.element.android.features.logout.api.LogoutEntryPoint import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.features.preferences.api.PreferencesEntryPoint @@ -118,7 +117,6 @@ class LoggedInFlowNode( private val shareEntryPoint: ShareEntryPoint, private val matrixClient: MatrixClient, private val sendingQueue: SendQueues, - private val logoutEntryPoint: LogoutEntryPoint, private val incomingVerificationEntryPoint: IncomingVerificationEntryPoint, private val mediaPreviewConfigMigration: MediaPreviewConfigMigration, private val sessionEnterpriseService: SessionEnterpriseService, @@ -276,9 +274,6 @@ class LoggedInFlowNode( @Parcelize data class IncomingShare(val intent: Intent) : NavTarget - @Parcelize - data object LogoutForNativeSlidingSyncMigrationNeeded : NavTarget - @Parcelize data class IncomingVerificationRequest(val data: VerificationRequest.Incoming) : NavTarget } @@ -323,10 +318,6 @@ class LoggedInFlowNode( override fun onReportBugClick() { plugins().forEach { it.onOpenBugReport() } } - - override fun onLogoutForNativeSlidingSyncMigrationNeeded() { - backstack.push(NavTarget.LogoutForNativeSlidingSyncMigrationNeeded) - } } homeEntryPoint .nodeBuilder(this, buildContext) @@ -480,17 +471,6 @@ class LoggedInFlowNode( .params(ShareEntryPoint.Params(intent = navTarget.intent)) .build() } - is NavTarget.LogoutForNativeSlidingSyncMigrationNeeded -> { - val callback = object : LogoutEntryPoint.Callback { - override fun onChangeRecoveryKeyClick() { - backstack.push(NavTarget.SecureBackup()) - } - } - - logoutEntryPoint.nodeBuilder(this, buildContext) - .callback(callback) - .build() - } is NavTarget.IncomingVerificationRequest -> { incomingVerificationEntryPoint.nodeBuilder(this, buildContext) .params(IncomingVerificationEntryPoint.Params(navTarget.data)) diff --git a/features/home/api/src/main/kotlin/io/element/android/features/home/api/HomeEntryPoint.kt b/features/home/api/src/main/kotlin/io/element/android/features/home/api/HomeEntryPoint.kt index 88b55d4e02..9beb147568 100644 --- a/features/home/api/src/main/kotlin/io/element/android/features/home/api/HomeEntryPoint.kt +++ b/features/home/api/src/main/kotlin/io/element/android/features/home/api/HomeEntryPoint.kt @@ -28,6 +28,5 @@ interface HomeEntryPoint : FeatureEntryPoint { fun onSessionConfirmRecoveryKeyClick() fun onRoomSettingsClick(roomId: RoomId) fun onReportBugClick() - fun onLogoutForNativeSlidingSyncMigrationNeeded() } } From c04962753aecdfc6d128a20fd274ea07bdef271f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 9 Sep 2025 15:19:19 +0200 Subject: [PATCH 002/145] Remove unused MatrixClient.availableSlidingSyncVersions(). --- .../android/appnav/loggedin/LoggedInPresenterTest.kt | 8 +------- .../element/android/libraries/matrix/api/MatrixClient.kt | 5 ----- .../android/libraries/matrix/impl/RustMatrixClient.kt | 6 ------ .../android/libraries/matrix/test/FakeMatrixClient.kt | 5 ----- 4 files changed, 1 insertion(+), 23 deletions(-) diff --git a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt index d86c46f159..47cbda4b91 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt @@ -501,22 +501,16 @@ class LoggedInPresenterTest { @Test fun `present - CheckSlidingSyncProxyAvailability forces the sliding sync migration under the right circumstances`() = runTest { - // The migration will be forced if: - // - The user is not using the native sliding sync - // - The sliding sync proxy is no longer supported - // - The native sliding sync is supported + // The migration will be forced if the user is not using the native sliding sync val matrixClient = FakeMatrixClient( currentSlidingSyncVersionLambda = { Result.success(SlidingSyncVersion.Proxy) }, - availableSlidingSyncVersionsLambda = { Result.success(listOf(SlidingSyncVersion.Native)) }, ) createLoggedInPresenter( matrixClient = matrixClient, ).test { val initialState = awaitItem() assertThat(initialState.forceNativeSlidingSyncMigration).isFalse() - initialState.eventSink(LoggedInEvents.CheckSlidingSyncProxyAvailability) - assertThat(awaitItem().forceNativeSlidingSyncMigration).isTrue() } } 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 bc7ec21152..db4439332b 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 @@ -156,11 +156,6 @@ interface MatrixClient { */ suspend fun currentSlidingSyncVersion(): Result - /** - * Returns the available sliding sync versions for the current user. - */ - suspend fun availableSlidingSyncVersions(): Result> - fun canDeactivateAccount(): Boolean suspend fun deactivateAccount(password: String, eraseData: Boolean): Result diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index e193d8f37d..a28bb232a4 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 @@ -689,12 +689,6 @@ class RustMatrixClient( }) }.buffer(Channel.UNLIMITED) - override suspend fun availableSlidingSyncVersions(): Result> = withContext(sessionDispatcher) { - runCatchingExceptions { - innerClient.availableSlidingSyncVersions().map { it.map() } - } - } - override suspend fun currentSlidingSyncVersion(): Result = withContext(sessionDispatcher) { runCatchingExceptions { innerClient.session().slidingSyncVersion.map() 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 199716bb90..4f7d42e5fb 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 @@ -90,7 +90,6 @@ class FakeMatrixClient( private val canDeactivateAccountResult: () -> Boolean = { lambdaError() }, private val deactivateAccountResult: (String, Boolean) -> Result = { _, _ -> lambdaError() }, private val currentSlidingSyncVersionLambda: () -> Result = { lambdaError() }, - private val availableSlidingSyncVersionsLambda: () -> Result> = { lambdaError() }, private val ignoreUserResult: (UserId) -> Result = { lambdaError() }, private var unIgnoreUserResult: (UserId) -> Result = { Result.success(Unit) }, private val canReportRoomLambda: () -> Boolean = { false }, @@ -339,10 +338,6 @@ class FakeMatrixClient( return currentSlidingSyncVersionLambda() } - override suspend fun availableSlidingSyncVersions(): Result> { - return availableSlidingSyncVersionsLambda() - } - override suspend fun canReportRoom(): Boolean { return canReportRoomLambda() } From b559065db9f389dd5dc86a1b4eb09fc2a37f244d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 9 Sep 2025 21:32:18 +0200 Subject: [PATCH 003/145] Changelog for version 25.09.1 --- CHANGES.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 93f947f3f7..5377aedff1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,61 @@ +Changes in Element X v25.09.1 +============================= + +## What's Changed + +We have migrated our DI libraries from Dagger and Anvil to Metro. If you need more details on the migration steps, please read the [documentation](https://github.com/element-hq/element-x-android/blob/develop/docs/migration_to_metro.md). + +### ✨ Features +* Allow replying to a message with an attachment by @jmartinesp in https://github.com/element-hq/element-x-android/pull/5261 +* Add emoji search to the reaction emoji picker by @jmartinesp in https://github.com/element-hq/element-x-android/pull/5255 +### 🙌 Improvements +* Spelling correction in Update FeatureFlags.kt by @escix in https://github.com/element-hq/element-x-android/pull/5232 +* [a11y] Add content descriptions to room list item indicators by @jmartinesp in https://github.com/element-hq/element-x-android/pull/5236 +* [a11y] Add click action to the message bottom sheet handle by @jmartinesp in https://github.com/element-hq/element-x-android/pull/5228 +### 🐛 Bugfixes +* Reload member list after moderation actions by @jmartinesp in https://github.com/element-hq/element-x-android/pull/5268 +* Restore view log code by @bmarty in https://github.com/element-hq/element-x-android/pull/5294 +* Detect mime type when picking a file by @bmarty in https://github.com/element-hq/element-x-android/pull/5291 +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/5249 +* Sync Strings - new translations to Korean by @ElementBot in https://github.com/element-hq/element-x-android/pull/5286 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/5290 +### 🧱 Build +* Iterate on build chain by @bmarty in https://github.com/element-hq/element-x-android/pull/5272 +* Cleanup our DI solution and add documentation about the migration to Metro by @bmarty in https://github.com/element-hq/element-x-android/pull/5287 +* Revert agp to 8.11 by @bmarty in https://github.com/element-hq/element-x-android/pull/5311 +### 🚧 In development 🚧 +* Space: add content in home screen by @bmarty in https://github.com/element-hq/element-x-android/pull/5273 +* Hide the home navigation bar if the user is not a member of any Space. by @bmarty in https://github.com/element-hq/element-x-android/pull/5292 +### Dependency upgrades +* Update dependency org.maplibre.gl:android-sdk to v11.13.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5239 +* Update dependency com.google.firebase:firebase-bom to v34.2.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5245 +* Update dependency com.posthog:posthog-android to v3.21.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5238 +* Update dependency org.matrix.rustcomponents:sdk-android to v25.9.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5251 +* Update plugin sonarqube to v6.3.1.5724 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5235 +* Update android.gradle.plugin to v8.12.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5244 +* Update dependency io.element.android:emojibase-bindings to v1.4.3 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5250 +* Update actions/setup-python action to v6 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5270 +* Update dependency com.posthog:posthog-android to v3.21.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5275 +* Migrate Anvil KSP to Metro by @jmartinesp in https://github.com/element-hq/element-x-android/pull/5253 +* Update actions/github-script action to v8 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5284 +* Update codecov/codecov-action action to v5.5.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5274 +* Update dependency io.sentry:sentry-android to v8.21.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/5293 +### Others +* Remove LoginUserStory. by @bmarty in https://github.com/element-hq/element-x-android/pull/5237 +* Update state in runUpdatingState when CancellationException occurs by @jbrenorv in https://github.com/element-hq/element-x-android/pull/5243 +* Refactor: Move InMemorySessionStore to test module by @bmarty in https://github.com/element-hq/element-x-android/pull/5252 +* Enable `largeHeap` option to have a larger max heap size by @jmartinesp in https://github.com/element-hq/element-x-android/pull/5258 +* Set a custom request config for the Client by @jmartinesp in https://github.com/element-hq/element-x-android/pull/5266 +* Set shortcut ID on received notifications to make them appear as a Conversation by @frebib in https://github.com/element-hq/element-x-android/pull/5192 +* Improve management of shortcut ids. by @bmarty in https://github.com/element-hq/element-x-android/pull/5303 + +## New Contributors +* @escix made their first contribution in https://github.com/element-hq/element-x-android/pull/5232 +* @jbrenorv made their first contribution in https://github.com/element-hq/element-x-android/pull/5243 + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v25.09.0...v25.09.1 + Changes in Element X v25.09.0 ============================= From 94f098d51714136a4f8d36272f796c60595cdeb6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Sep 2025 11:32:27 +0200 Subject: [PATCH 004/145] Release script: read the build tool version from Versions.kt --- plugins/src/main/kotlin/Versions.kt | 5 +++-- tools/release/release.sh | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index f02b468b6e..4a26320bb8 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -38,9 +38,10 @@ object Versions { const val VERSION_CODE = (2000 + versionYear) * 10_000 + versionMonth * 100 + versionReleaseNumber val VERSION_NAME = "$versionYear.${versionMonth.toString().padStart(2, '0')}.$versionReleaseNumber" - // When updating COMPILE_SDK, please do not forget to update the value for `buildToolsVersion` - // in the file `tools/release/release.sh` + // When updating COMPILE_SDK, please also update BUILD_TOOLS_VERSION const val COMPILE_SDK = 36 + @Suppress("unused") + private const val BUILD_TOOLS_VERSION = "36.0.0" const val TARGET_SDK = 36 // When updating the `minSdk`, make sure to update the value of `minSdkVersion` in the file `tools/release/release.sh` diff --git a/tools/release/release.sh b/tools/release/release.sh index 30d4cea205..6727ebb309 100755 --- a/tools/release/release.sh +++ b/tools/release/release.sh @@ -64,7 +64,8 @@ fi # Read minSdkVersion from file plugins/src/main/kotlin/Versions.kt minSdkVersion=$(grep "MIN_SDK_FOSS =" ./plugins/src/main/kotlin/Versions.kt |cut -d '=' -f 2 |xargs) -buildToolsVersion="36.0.0" +# Read buildToolsVersion from file plugins/src/main/kotlin/Versions.kt +buildToolsVersion=$(grep "BUILD_TOOLS_VERSION =" ./plugins/src/main/kotlin/Versions.kt |cut -d '=' -f 2 |xargs) buildToolsPath="${androidHome}/build-tools/${buildToolsVersion}" if [[ ! -d ${buildToolsPath} ]]; then From ac9c75dded45c4ca179195c53332318caae1457f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Sep 2025 11:34:26 +0200 Subject: [PATCH 005/145] Remove obsolete comment. The release script now reads the value from Versions.kt --- plugins/src/main/kotlin/Versions.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 4a26320bb8..d180867444 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -44,7 +44,6 @@ object Versions { private const val BUILD_TOOLS_VERSION = "36.0.0" const val TARGET_SDK = 36 - // When updating the `minSdk`, make sure to update the value of `minSdkVersion` in the file `tools/release/release.sh` private const val MIN_SDK_FOSS = 24 private const val MIN_SDK_ENTERPRISE = 33 val minSdk = if (isEnterpriseBuild) MIN_SDK_ENTERPRISE else MIN_SDK_FOSS From c3db71b623c03994ae8309011ab1b12044814c74 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Sep 2025 11:46:02 +0200 Subject: [PATCH 006/145] Add static checks --- plugins/src/main/kotlin/Versions.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index d180867444..dd312f9faa 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -40,6 +40,7 @@ object Versions { // When updating COMPILE_SDK, please also update BUILD_TOOLS_VERSION const val COMPILE_SDK = 36 + @Suppress("unused") private const val BUILD_TOOLS_VERSION = "36.0.0" const val TARGET_SDK = 36 @@ -51,4 +52,11 @@ object Versions { private const val JAVA_VERSION = 21 val javaVersion: JavaVersion = JavaVersion.toVersion(JAVA_VERSION) val javaLanguageVersion: JavaLanguageVersion = JavaLanguageVersion.of(JAVA_VERSION) + + // Perform some checks on the values to avoid releasing with bad values + init { + require(versionMonth in 1..12) { "versionMonth must be in [1,12]" } + require(versionReleaseNumber in 0..99) { "versionReleaseNumber must be in [0,99]" } + require(BUILD_TOOLS_VERSION.startsWith(COMPILE_SDK.toString())) { "When updating COMPILE_SDK, please also update BUILD_TOOLS_VERSION" } + } } From 7fcc090cc68e15a3291bd255ca72a21617c35786 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Sep 2025 11:58:38 +0200 Subject: [PATCH 007/145] Document Versions.kt --- plugins/src/main/kotlin/Versions.kt | 53 ++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index dd312f9faa..14307ae741 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -13,9 +13,9 @@ import org.gradle.jvm.toolchain.JavaLanguageVersion * Max versionCode allowed by the PlayStore (for information): * 2_100_000_000 * - * Also note that the versionCode is multiplied by 10 in app/build.gradle.kts#L168: + * Also note that the versionCode is multiplied by 10 in app/build.gradle.kts: * ``` - * output.versionCode.set((output.versionCode.get() ?: 0) * 10 + abiCode)) + * output.versionCode.set((output.versionCode.orNull ?: 0) * 10 + abiCode) * ``` * We are using a CalVer-like approach to version the application. The version code is calculated as follows: * - 2 digits for the year @@ -28,28 +28,73 @@ import org.gradle.jvm.toolchain.JavaLanguageVersion * - the version code: 20250100a (202_501_00a) where `a` stands for the architecture code */ +/** + * Year of the version on 2 digits. + * Do not update this value. it is updated by the release script. + */ private const val versionYear = 25 + +/** + * Month of the version on 2 digits. Value must be in [1,12]. + * Do not update this value. it is updated by the release script. + */ private const val versionMonth = 9 -// Note: must be in [0,99] +/** + * Release number in the month. Value must be in [0,99]. + * Do not update this value. it is updated by the release script. + */ private const val versionReleaseNumber = 1 object Versions { + /** + * Base version code that will be set in the Android Manifest. + * The value will be modified at build time to add the ABI code when APK are build. + * AAB will have a ABI code of 0. + * See comment above for the calculation method. + */ const val VERSION_CODE = (2000 + versionYear) * 10_000 + versionMonth * 100 + versionReleaseNumber val VERSION_NAME = "$versionYear.${versionMonth.toString().padStart(2, '0')}.$versionReleaseNumber" - // When updating COMPILE_SDK, please also update BUILD_TOOLS_VERSION + /** + * Compile SDK version. Must be updated when a new Android version is released. + * When updating COMPILE_SDK, please also update BUILD_TOOLS_VERSION. + */ const val COMPILE_SDK = 36 + /** + * Build tools version. Must be kept in sync with COMPILE_SDK. + * The value is used by the release script. + */ @Suppress("unused") private const val BUILD_TOOLS_VERSION = "36.0.0" + + /** + * Target SDK version. Should be kept up to date with COMPILE_SDK. + */ const val TARGET_SDK = 36 + /** + * Minimum SDK version for FOSS builds. + */ private const val MIN_SDK_FOSS = 24 + + /** + * Minimum SDK version for Enterprise builds. + */ private const val MIN_SDK_ENTERPRISE = 33 + + /** + * minSdkVersion that will be set in the Android Manifest. + */ val minSdk = if (isEnterpriseBuild) MIN_SDK_ENTERPRISE else MIN_SDK_FOSS + /** + * Java version used for compilation. + * Update this value when you want to use a newer Java version. + */ private const val JAVA_VERSION = 21 + val javaVersion: JavaVersion = JavaVersion.toVersion(JAVA_VERSION) val javaLanguageVersion: JavaLanguageVersion = JavaLanguageVersion.of(JAVA_VERSION) From 7e0931c299774b4fdb668bc17c3fcb3c5f1ac215 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 10 Sep 2025 12:47:12 +0200 Subject: [PATCH 008/145] Increase Element Call audio init delay (#5315) This fixed the wrong audio stream being used when starting a call locally. --- .../android/features/call/impl/utils/WebViewAudioManager.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt index 51f758a3bb..7745cda13b 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt @@ -29,7 +29,7 @@ import kotlinx.serialization.json.Json import timber.log.Timber import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicBoolean -import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds /** * This class manages the audio devices for a WebView. @@ -246,7 +246,6 @@ class WebViewAudioManager( private fun registerWebViewDeviceSelectedCallback() { val webViewAudioDeviceSelectedCallback = AndroidWebViewAudioBridge( onAudioDeviceSelected = { selectedDeviceId -> - Timber.d("Audio device selected in webview, id: $selectedDeviceId") previousSelectedDevice = listAudioDevices().find { it.id.toString() == selectedDeviceId } audioManager.selectAudioDevice(selectedDeviceId) }, @@ -254,7 +253,7 @@ class WebViewAudioManager( coroutineScope.launch(Dispatchers.Main) { // Even with the callback, it seems like starting the audio takes a bit on the webview side, // so we add an extra delay here to make sure it's ready - delay(500.milliseconds) + delay(2.seconds) // Calling this ahead of time makes the default audio device to not use the right audio stream setAvailableAudioDevices() From aadd8b45e2aec690c335b0a403e80dea601ccd98 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 5 Sep 2025 10:27:33 +0200 Subject: [PATCH 009/145] feature(spaces) : introduce SpaceRoomList matrix api --- .../home/impl/spaces/HomeSpacesPresenter.kt | 5 +- .../home/impl/spaces/HomeSpacesState.kt | 3 +- .../impl/spaces/HomeSpacesStateProvider.kt | 14 +-- .../home/impl/spaces/HomeSpacesView.kt | 9 +- .../home/impl/spaces/SpaceRoomProvider.kt | 26 ++--- .../features/invite/api/SeenInvitesStore.kt | 6 -- .../libraries/matrix/api/spaces/SpaceRoom.kt | 4 +- .../matrix/api/spaces/SpaceRoomList.kt | 23 +++++ .../matrix/api/spaces/SpaceService.kt | 5 +- .../matrix/impl/spaces/RustSpaceRoomList.kt | 56 +++++++++++ .../matrix/impl/spaces/RustSpaceService.kt | 96 ++++--------------- .../impl/spaces/SpaceListUpdateProcessor.kt | 86 +++++++++++++++++ .../impl/spaces/SpaceRoomListExtensions.kt | 54 +++++++++++ .../matrix/impl/spaces/SpaceRoomMapper.kt | 3 +- .../matrix/ui/model/SpaceExtension.kt | 2 +- 15 files changed, 277 insertions(+), 115 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomListExtensions.kt diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt index 29ceca14bf..b29da29a94 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt @@ -13,7 +13,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import dev.zacsweers.metro.Inject import io.element.android.features.invite.api.SeenInvitesStore -import io.element.android.features.invite.api.seenSpaceIds import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.matrix.api.MatrixClient @@ -34,9 +33,9 @@ class HomeSpacesPresenter( .mediaPreviewConfigFlow .mapState { config -> config.hideInviteAvatar } }.collectAsState() - val spaceRooms by client.spaceService.spaceRooms.collectAsState(emptyList()) + val spaceRooms by client.spaceService.spaceRoomsFlow.collectAsState(emptyList()) val seenSpaceInvites by remember { - seenInvitesStore.seenSpaceIds().map { it.toPersistentSet() } + seenInvitesStore.seenRoomIds().map { it.toPersistentSet() } }.collectAsState(persistentSetOf()) fun handleEvents(event: HomeSpacesEvents) { diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt index 6def46c7b3..39871fb905 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt @@ -7,6 +7,7 @@ package io.element.android.features.home.impl.spaces +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.collections.immutable.ImmutableSet @@ -14,7 +15,7 @@ import kotlinx.collections.immutable.ImmutableSet data class HomeSpacesState( val space: CurrentSpace, val spaceRooms: List, - val seenSpaceInvites: ImmutableSet, + val seenSpaceInvites: ImmutableSet, val hideInvitesAvatar: Boolean, val eventSink: (HomeSpacesEvents) -> Unit, ) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt index 466f515b26..1aedc0ef19 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt @@ -8,7 +8,7 @@ package io.element.android.features.home.impl.spaces import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.libraries.matrix.api.core.SpaceId +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.collections.immutable.toImmutableSet @@ -18,12 +18,12 @@ open class HomeSpacesStateProvider : PreviewParameterProvider { aHomeSpacesState( spaceRooms = SpaceRoomProvider().values.toList(), seenSpaceInvites = setOf( - SpaceId("!spaceId3:example.com"), + RoomId("!spaceId3:example.com"), ), ), aHomeSpacesState( space = CurrentSpace.Space( - spaceRoom = aSpaceRooms(spaceId = SpaceId("!mySpace:example.com")) + spaceRoom = aSpaceRoom(roomId = RoomId("!mySpace:example.com")) ), spaceRooms = aListOfSpaceRooms(), ), @@ -33,7 +33,7 @@ open class HomeSpacesStateProvider : PreviewParameterProvider { internal fun aHomeSpacesState( space: CurrentSpace = CurrentSpace.Root, spaceRooms: List = aListOfSpaceRooms(), - seenSpaceInvites: Set = emptySet(), + seenSpaceInvites: Set = emptySet(), hideInvitesAvatar: Boolean = false, eventSink: (HomeSpacesEvents) -> Unit = {}, ) = HomeSpacesState( @@ -46,8 +46,8 @@ internal fun aHomeSpacesState( fun aListOfSpaceRooms(): List { return listOf( - aSpaceRooms(spaceId = SpaceId("!spaceId0:example.com")), - aSpaceRooms(spaceId = SpaceId("!spaceId1:example.com")), - aSpaceRooms(spaceId = SpaceId("!spaceId2:example.com")), + aSpaceRoom(roomId = RoomId("!spaceId0:example.com")), + aSpaceRoom(roomId = RoomId("!spaceId1:example.com")), + aSpaceRoom(roomId = RoomId("!spaceId2:example.com")), ) } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt index be6639e94b..ae1cf09751 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.ui.components.SpaceHeaderRootView @@ -24,7 +25,7 @@ import kotlinx.collections.immutable.toImmutableList @Composable fun HomeSpacesView( state: HomeSpacesState, - onSpaceClick: (SpaceId) -> Unit, + onSpaceClick: (RoomId) -> Unit, modifier: Modifier = Modifier, ) { LazyColumn(modifier) { @@ -52,14 +53,14 @@ fun HomeSpacesView( } } state.spaceRooms.forEach { - item(it.spaceId) { + item(it.roomId) { val isInvitation = it.state == CurrentUserMembership.INVITED HomeSpaceItemView( spaceRoom = it, - showUnreadIndicator = isInvitation && it.spaceId !in state.seenSpaceInvites, + showUnreadIndicator = isInvitation && it.roomId !in state.seenSpaceInvites, hideAvatars = isInvitation && state.hideInvitesAvatar, onClick = { - onSpaceClick(it.spaceId) + onSpaceClick(it.roomId) } ) } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/SpaceRoomProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/SpaceRoomProvider.kt index 29c18c78a0..88c3c5799a 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/SpaceRoomProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/SpaceRoomProvider.kt @@ -9,7 +9,7 @@ package io.element.android.features.home.impl.spaces import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.matrix.api.core.RoomAlias -import io.element.android.libraries.matrix.api.core.SpaceId +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomType import io.element.android.libraries.matrix.api.room.join.JoinRule @@ -18,42 +18,42 @@ import io.element.android.libraries.matrix.api.user.MatrixUser class SpaceRoomProvider : PreviewParameterProvider { override val values: Sequence = sequenceOf( - aSpaceRooms(), - aSpaceRooms( + aSpaceRoom(), + aSpaceRoom( numJoinedMembers = 5, childrenCount = 10, worldReadable = true, - spaceId = SpaceId("!spaceId0:example.com"), + roomId = RoomId("!spaceId0:example.com"), ), - aSpaceRooms( + aSpaceRoom( numJoinedMembers = 5, childrenCount = 10, worldReadable = true, avatarUrl = "anUrl", - spaceId = SpaceId("!spaceId1:example.com"), + roomId = RoomId("!spaceId1:example.com"), ), - aSpaceRooms( + aSpaceRoom( name = null, numJoinedMembers = 5, childrenCount = 10, worldReadable = true, avatarUrl = "anUrl", - spaceId = SpaceId("!spaceId2:example.com"), + roomId = RoomId("!spaceId2:example.com"), state = CurrentUserMembership.INVITED, ), - aSpaceRooms( + aSpaceRoom( name = null, numJoinedMembers = 5, childrenCount = 10, worldReadable = true, avatarUrl = "anUrl", - spaceId = SpaceId("!spaceId3:example.com"), + roomId = RoomId("!spaceId3:example.com"), state = CurrentUserMembership.INVITED, ), ) } -fun aSpaceRooms( +fun aSpaceRoom( name: String? = "Space name", avatarUrl: String? = null, canonicalAlias: RoomAlias? = null, @@ -62,7 +62,7 @@ fun aSpaceRooms( heroes: List = emptyList(), joinRule: JoinRule? = null, numJoinedMembers: Int = 0, - spaceId: SpaceId = SpaceId("!spaceId:example.com"), + roomId: RoomId = RoomId("!roomId:example.com"), roomType: RoomType = RoomType.Space, state: CurrentUserMembership? = null, topic: String? = null, @@ -76,7 +76,7 @@ fun aSpaceRooms( heroes = heroes, joinRule = joinRule, numJoinedMembers = numJoinedMembers, - spaceId = spaceId, + roomId = roomId, roomType = roomType, state = state, topic = topic, diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt index 6c609e3810..283deb78fb 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt @@ -38,9 +38,3 @@ interface SeenInvitesStore { */ suspend fun clear() } - -fun SeenInvitesStore.seenSpaceIds(): Flow> { - return seenRoomIds().map { roomIds -> - roomIds.map { it.toSpaceId() }.toSet() - } -} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt index ce697089c7..102e594ea7 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt @@ -8,7 +8,7 @@ package io.element.android.libraries.matrix.api.spaces import io.element.android.libraries.matrix.api.core.RoomAlias -import io.element.android.libraries.matrix.api.core.SpaceId +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomType import io.element.android.libraries.matrix.api.room.join.JoinRule @@ -23,7 +23,7 @@ data class SpaceRoom( val heroes: List, val joinRule: JoinRule?, val numJoinedMembers: Int, - val spaceId: SpaceId, + val roomId: RoomId, val roomType: RoomType, val state: CurrentUserMembership?, val topic: String?, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt new file mode 100644 index 0000000000..a1f79cdb0b --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.spaces + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow + +interface SpaceRoomList { + sealed interface PaginationStatus { + data object Loading : PaginationStatus + data class Idle(val hasMoreToLoad: Boolean) : PaginationStatus + } + + val spaceRoomsFlow: Flow> + val paginationStatusFlow: StateFlow + suspend fun paginate(): Result +} + diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt index 58494502f7..917369a6a7 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt @@ -7,9 +7,12 @@ package io.element.android.libraries.matrix.api.spaces +import io.element.android.libraries.matrix.api.core.SpaceId import kotlinx.coroutines.flow.SharedFlow interface SpaceService { - val spaceRooms: SharedFlow> + val spaceRoomsFlow: SharedFlow> suspend fun joinedSpaces(): Result> + + suspend fun spaceRoomList(spaceId: SpaceId): SpaceRoomList } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt new file mode 100644 index 0000000000..efe405714e --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.spaces + +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import io.element.android.libraries.matrix.api.spaces.SpaceRoomList +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState +import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList + +class RustSpaceRoomList( + private val inner: InnerSpaceRoomList, + sessionCoroutineScope: CoroutineScope, + spaceRoomMapper: SpaceRoomMapper, +) : SpaceRoomList { + override val spaceRoomsFlow = MutableSharedFlow>(replay = 1, extraBufferCapacity = Int.MAX_VALUE) + override val paginationStatusFlow = MutableStateFlow(inner.paginationState().into()) + private val spaceListUpdateProcessor = SpaceListUpdateProcessor(spaceRoomsFlow, spaceRoomMapper) + + init { + inner.paginationStateFlow() + .onEach { paginationStatus -> + paginationStatusFlow.emit(paginationStatus.into()) + } + .launchIn(sessionCoroutineScope) + + inner.spaceListUpdateFlow() + .onEach { updates -> + spaceListUpdateProcessor.postUpdates(updates) + } + .launchIn(sessionCoroutineScope) + } + + override suspend fun paginate(): Result { + return runCatchingExceptions { + inner.paginate() + } + } + + private fun SpaceRoomListPaginationState.into(): SpaceRoomList.PaginationStatus { + return when (this) { + is SpaceRoomListPaginationState.Idle -> SpaceRoomList.PaginationStatus.Idle(hasMoreToLoad = !endReached) + SpaceRoomListPaginationState.Loading -> SpaceRoomList.PaginationStatus.Loading + } + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt index b059d476bc..4d26040021 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt @@ -8,7 +8,9 @@ package io.element.android.libraries.matrix.impl.spaces import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import io.element.android.libraries.matrix.api.spaces.SpaceRoomList import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.libraries.matrix.impl.util.cancelAndDestroy import kotlinx.coroutines.CoroutineDispatcher @@ -21,11 +23,8 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.SpaceListUpdate import org.matrix.rustcomponents.sdk.SpaceServiceInterface @@ -38,104 +37,49 @@ class RustSpaceService( private val sessionCoroutineScope: CoroutineScope, private val sessionDispatcher: CoroutineDispatcher, ) : SpaceService { - private val mapper = SpaceRoomMapper() - private val mutex = Mutex() - - override val spaceRooms = MutableSharedFlow>(replay = 1, extraBufferCapacity = 1) + private val spaceRoomMapper = SpaceRoomMapper() + override val spaceRoomsFlow = MutableSharedFlow>(replay = 1, extraBufferCapacity = 1) + private val spaceListUpdateProcessor = SpaceListUpdateProcessor(spaceRoomsFlow, spaceRoomMapper) override suspend fun joinedSpaces(): Result> = withContext(sessionDispatcher) { runCatchingExceptions { innerSpaceService.joinedSpaces() .map { - it.let(mapper::map) + it.let(spaceRoomMapper::map) } } } - // override suspend fun spaceRoomList(spaceId: SpaceId): Result> = withContext(sessionDispatcher) { - // runCatchingExceptions { - // innerSpaceService.spaceRoomList(spaceId.value) - // } - // } + override suspend fun spaceRoomList(spaceId: SpaceId): SpaceRoomList { + val innerSpaceRoomList = innerSpaceService.spaceRoomList(spaceId.value) + return RustSpaceRoomList( + inner = innerSpaceRoomList, + sessionCoroutineScope = sessionCoroutineScope, + spaceRoomMapper = spaceRoomMapper + ) + } init { innerSpaceService - .spaceDiffFlow() - .onEach { - handeUpdate(it) + .spaceListUpdate() + .onEach { updates -> + spaceListUpdateProcessor.postUpdates(updates) } .launchIn(sessionCoroutineScope) } - - private suspend fun handeUpdate(spaceListUpdates: List) { - mutex.withLock { - val current = if (spaceRooms.replayCache.isNotEmpty()) { - spaceRooms.first().toMutableList() - } else { - mutableListOf() - } - spaceListUpdates.forEach { update -> - current.applyUpdate(update) - } - spaceRooms.emit(current) - } - } - - private fun MutableList.applyUpdate(update: SpaceListUpdate) { - when (update) { - is SpaceListUpdate.Append -> { - val newSpaces = update.values.map(mapper::map) - addAll(newSpaces) - } - SpaceListUpdate.Clear -> clear() - is SpaceListUpdate.Insert -> { - val newSpace = mapper.map(update.value) - add(update.index.toInt(), newSpace) - } - SpaceListUpdate.PopBack -> { - removeAt(lastIndex) - } - SpaceListUpdate.PopFront -> { - removeAt(0) - } - is SpaceListUpdate.PushBack -> { - val newSpace = mapper.map(update.value) - add(newSpace) - } - is SpaceListUpdate.PushFront -> { - val newSpace = mapper.map(update.value) - add(0, newSpace) - } - is SpaceListUpdate.Remove -> { - removeAt(update.index.toInt()) - } - is SpaceListUpdate.Reset -> { - clear() - val newSpaces = update.values.map(mapper::map) - addAll(newSpaces) - } - is SpaceListUpdate.Set -> { - val newSpace = mapper.map(update.value) - this[update.index.toInt()] = newSpace - } - is SpaceListUpdate.Truncate -> { - subList(update.length.toInt(), size).clear() - } - } - } } -internal fun SpaceServiceInterface.spaceDiffFlow(): Flow> = +internal fun SpaceServiceInterface.spaceListUpdate(): Flow> = callbackFlow { val listener = object : SpaceServiceJoinedSpacesListener { override fun onUpdate(roomUpdates: List) { trySendBlocking(roomUpdates) } } - Timber.d("Open spaceDiffFlow for SpaceServiceInterface ${this@spaceDiffFlow}") + Timber.d("Open spaceDiffFlow for SpaceServiceInterface ${this@spaceListUpdate}") val taskHandle = subscribeToJoinedSpaces(listener) awaitClose { - Timber.d("Close spaceDiffFlow for SpaceServiceInterface ${this@spaceDiffFlow}") + Timber.d("Close spaceDiffFlow for SpaceServiceInterface ${this@spaceListUpdate}") taskHandle.cancelAndDestroy() } }.catch { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt new file mode 100644 index 0000000000..a1f8584299 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.spaces + +import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import org.matrix.rustcomponents.sdk.SpaceListUpdate +import timber.log.Timber + +internal class SpaceListUpdateProcessor( + private val spaceRoomsFlow: MutableSharedFlow>, + private val mapper: SpaceRoomMapper, +) { + private val mutex = Mutex() + + suspend fun postUpdates(updates: List) { + Timber.v("Update space rooms from postUpdates (with ${updates.size} items) on ${Thread.currentThread()}") + updateSpaceRooms { + updates.forEach { update -> applyUpdate(update) } + } + } + + private suspend fun updateSpaceRooms(block: MutableList.() -> Unit) = + mutex.withLock { + val spaceRooms = if (spaceRoomsFlow.replayCache.isNotEmpty()) { + spaceRoomsFlow.first().toMutableList() + } else { + mutableListOf() + } + block(spaceRooms) + spaceRoomsFlow.tryEmit(spaceRooms) + } + + private fun MutableList.applyUpdate(update: SpaceListUpdate) { + when (update) { + is SpaceListUpdate.Append -> { + val newSpaces = update.values.map { it -> + it.let(mapper::map) + } + addAll(newSpaces) + } + SpaceListUpdate.Clear -> clear() + is SpaceListUpdate.Insert -> { + val newSpace = mapper.map(update.value) + add(update.index.toInt(), newSpace) + } + SpaceListUpdate.PopBack -> { + removeAt(lastIndex) + } + SpaceListUpdate.PopFront -> { + removeAt(0) + } + is SpaceListUpdate.PushBack -> { + val newSpace = mapper.map(update.value) + add(newSpace) + } + is SpaceListUpdate.PushFront -> { + val newSpace = mapper.map(update.value) + add(0, newSpace) + } + is SpaceListUpdate.Remove -> { + removeAt(update.index.toInt()) + } + is SpaceListUpdate.Reset -> { + clear() + val newSpaces = update.values.map(mapper::map) + addAll(newSpaces) + } + is SpaceListUpdate.Set -> { + val newSpace = mapper.map(update.value) + this[update.index.toInt()] = newSpace + } + is SpaceListUpdate.Truncate -> { + subList(update.length.toInt(), size).clear() + } + } + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomListExtensions.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomListExtensions.kt new file mode 100644 index 0000000000..4976f37117 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomListExtensions.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.spaces + +import io.element.android.libraries.matrix.impl.util.cancelAndDestroy +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.buffer +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.catch +import org.matrix.rustcomponents.sdk.SpaceListUpdate +import org.matrix.rustcomponents.sdk.SpaceRoomListEntriesListener +import org.matrix.rustcomponents.sdk.SpaceRoomListInterface +import org.matrix.rustcomponents.sdk.SpaceRoomListPaginationStateListener +import timber.log.Timber +import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState + +internal fun SpaceRoomListInterface.paginationStateFlow(): Flow = callbackFlow { + val listener = object : SpaceRoomListPaginationStateListener { + override fun onUpdate(paginationState: SpaceRoomListPaginationState) { + trySend(paginationState) + } + } + val result = subscribeToPaginationStateUpdates(listener) + awaitClose { + result.cancelAndDestroy() + } +}.catch { + Timber.d(it, "paginationStateFlow() failed") +}.buffer(Channel.UNLIMITED) + +internal fun SpaceRoomListInterface.spaceListUpdateFlow(): Flow> = + callbackFlow { + val listener = object : SpaceRoomListEntriesListener { + override fun onUpdate(rooms: List) { + trySendBlocking(rooms) + } + } + Timber.d("Open spaceListUpdateFlow for SpaceRoomListInterface ${this@spaceListUpdateFlow}") + val taskHandle = subscribeToRoomUpdate(listener) + awaitClose { + Timber.d("Close spaceListUpdateFlow for SpaceRoomListInterface ${this@spaceListUpdateFlow}") + taskHandle.cancelAndDestroy() + } + }.catch { + Timber.d(it, "spaceListUpdateFlow() failed") + }.buffer(Channel.UNLIMITED) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt index 5622ee2c8c..ade5063515 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.spaces import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.matrix.api.core.RoomAlias +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.impl.room.join.map @@ -26,7 +27,7 @@ class SpaceRoomMapper { joinRule = spaceRoom.joinRule?.map(), name = spaceRoom.name, numJoinedMembers = spaceRoom.numJoinedMembers.toInt(), - spaceId = spaceRoom.roomId.let(::SpaceId), + roomId = RoomId(spaceRoom.roomId), roomType = spaceRoom.roomType.map(), state = spaceRoom.state?.map(), topic = spaceRoom.topic, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/SpaceExtension.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/SpaceExtension.kt index afe03b6877..e4b056fdea 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/SpaceExtension.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/SpaceExtension.kt @@ -12,7 +12,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.spaces.SpaceRoom fun SpaceRoom.getAvatarData(size: AvatarSize) = AvatarData( - id = spaceId.value, + id = roomId.value, name = name, url = avatarUrl, size = size, From 5d8ca6590e74d01f42c0fb8137d999e68a215935 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 5 Sep 2025 16:07:37 +0200 Subject: [PATCH 010/145] feature (space) : extract SpaceRoomItemView --- .../home/impl/spaces/HomeSpacesView.kt | 7 +- .../libraries/matrix/api/spaces/SpaceRoom.kt | 4 +- .../matrix/ui/components/SpaceRoomItemView.kt | 140 +++++++++++------- 3 files changed, 96 insertions(+), 55 deletions(-) rename features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpaceItemView.kt => libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt (66%) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt index ae1cf09751..cb93b297be 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt @@ -15,10 +15,10 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.ui.components.SpaceHeaderRootView import io.element.android.libraries.matrix.ui.components.SpaceHeaderView +import io.element.android.libraries.matrix.ui.components.SpaceRoomItemView import io.element.android.libraries.matrix.ui.model.getAvatarData import kotlinx.collections.immutable.toImmutableList @@ -55,12 +55,15 @@ fun HomeSpacesView( state.spaceRooms.forEach { item(it.roomId) { val isInvitation = it.state == CurrentUserMembership.INVITED - HomeSpaceItemView( + SpaceRoomItemView( spaceRoom = it, showUnreadIndicator = isInvitation && it.roomId !in state.seenSpaceInvites, hideAvatars = isInvitation && state.hideInvitesAvatar, onClick = { onSpaceClick(it.roomId) + }, + onLongClick = { + } ) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt index 102e594ea7..d4e1d57826 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt @@ -28,4 +28,6 @@ data class SpaceRoom( val state: CurrentUserMembership?, val topic: String?, val worldReadable: Boolean, -) +) { + val isSpace = roomType == RoomType.Space +} diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpaceItemView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt similarity index 66% rename from features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpaceItemView.kt rename to libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt index 461c550d8e..be540d486d 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpaceItemView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.home.impl.spaces +package io.element.android.libraries.matrix.ui.components import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -22,88 +22,66 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material3.ripple import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle 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.atomic.atoms.UnreadIndicatorAtom import io.element.android.libraries.designsystem.atomic.molecules.InviteButtonsRowMolecule import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.modifiers.onKeyboardContextMenuAction -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.unreadIndicator import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.ui.strings.CommonPlurals import io.element.android.libraries.ui.strings.CommonStrings @Composable -internal fun HomeSpaceItemView( +fun SpaceRoomItemView( spaceRoom: SpaceRoom, showUnreadIndicator: Boolean, hideAvatars: Boolean, onClick: () -> Unit, + onLongClick: () -> Unit, modifier: Modifier = Modifier, ) { - SpaceScaffoldRow( + SpaceRoomItemScaffold( modifier = modifier, - spaceRoom = spaceRoom, - onClick = onClick, + avatarData = spaceRoom.getAvatarData(AvatarSize.SpaceListItem), + isSpace = spaceRoom.isSpace, hideAvatars = hideAvatars, - onLongClick = { }, + onClick = onClick, + onLongClick = onLongClick, ) { NameAndIndicatorRow( name = spaceRoom.name, - showIndicator = showUnreadIndicator, + showIndicator = showUnreadIndicator ) Spacer(modifier = Modifier.height(1.dp)) - if (!spaceRoom.worldReadable) { - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - ) { - Icon( - modifier = Modifier - .size(16.dp) - .padding(end = 4.dp), - imageVector = CompoundIcons.LockSolid(), - contentDescription = null, - tint = ElementTheme.colors.iconTertiary, - ) - Text( - modifier = Modifier.weight(1f), - style = ElementTheme.typography.fontBodyMdRegular, - text = stringResource(CommonStrings.common_private_space), - fontStyle = FontStyle.Italic.takeIf { spaceRoom.name == null }, - color = ElementTheme.colors.textSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - Spacer(modifier = Modifier.height(1.dp)) - } - val spaceSummary = stringResource( - CommonStrings.screen_space_list_details, - pluralStringResource(CommonPlurals.common_rooms, spaceRoom.childrenCount, spaceRoom.childrenCount), - pluralStringResource(CommonPlurals.common_member_count, spaceRoom.numJoinedMembers, spaceRoom.numJoinedMembers), + SubtitleRow( + visibilityIcon = spaceRoom.visibilityIcon(), + subtitle = spaceRoom.subtitle() ) + Spacer(modifier = Modifier.height(1.dp)) Text( modifier = Modifier.weight(1f), style = ElementTheme.typography.fontBodyMdRegular, - text = spaceSummary, + text = spaceRoom.info(), fontStyle = FontStyle.Italic.takeIf { spaceRoom.name == null }, color = ElementTheme.colors.textSecondary, maxLines = 1, @@ -119,6 +97,37 @@ internal fun HomeSpaceItemView( } } +@Composable +private fun SubtitleRow( + visibilityIcon: ImageVector?, + subtitle: String, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + ) { + if (visibilityIcon != null) { + Icon( + modifier = Modifier + .size(16.dp) + .padding(end = 4.dp), + imageVector = visibilityIcon, + contentDescription = null, + tint = ElementTheme.colors.iconTertiary, + ) + } + Text( + modifier = Modifier.weight(1f), + style = ElementTheme.typography.fontBodyMdRegular, + text = subtitle, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } +} + @Composable private fun NameAndIndicatorRow( name: String?, @@ -148,8 +157,9 @@ private fun NameAndIndicatorRow( } @Composable -private fun SpaceScaffoldRow( - spaceRoom: SpaceRoom, +private fun SpaceRoomItemScaffold( + avatarData: AvatarData, + isSpace: Boolean, onClick: () -> Unit, onLongClick: () -> Unit, hideAvatars: Boolean, @@ -173,8 +183,8 @@ private fun SpaceScaffoldRow( .height(IntrinsicSize.Min), ) { Avatar( - avatarData = spaceRoom.getAvatarData(AvatarSize.SpaceListItem), - avatarType = AvatarType.Space(), + avatarData = avatarData, + avatarType = if (isSpace) AvatarType.Space() else AvatarType.Room(), hideImage = hideAvatars, ) Spacer(modifier = Modifier.width(16.dp)) @@ -185,13 +195,39 @@ private fun SpaceScaffoldRow( } } -@PreviewsDayNight @Composable -internal fun HomeSpaceItemViewPreview(@PreviewParameter(SpaceRoomProvider::class) spaceRoom: SpaceRoom) = ElementPreview { - HomeSpaceItemView( - spaceRoom = spaceRoom, - showUnreadIndicator = false, - hideAvatars = true, - onClick = {}, - ) +@ReadOnlyComposable +private fun SpaceRoom.subtitle(): String { + return if (isSpace) { + if (joinRule == JoinRule.Public) { + stringResource(CommonStrings.common_public_space) + } else { + stringResource(CommonStrings.common_private_space) + } + } else { + pluralStringResource(CommonPlurals.common_member_count, numJoinedMembers, numJoinedMembers) + } +} + +@Composable +@ReadOnlyComposable +private fun SpaceRoom.info(): String { + return if (isSpace) { + stringResource( + CommonStrings.screen_space_list_details, + pluralStringResource(CommonPlurals.common_rooms, childrenCount, childrenCount), + pluralStringResource(CommonPlurals.common_member_count, numJoinedMembers, numJoinedMembers), + ) + } else { + topic.orEmpty() + } +} + +@Composable +private fun SpaceRoom.visibilityIcon(): ImageVector? { + return if (joinRule == JoinRule.Public) { + CompoundIcons.Public() + } else { + CompoundIcons.LockSolid() + } } From 4048bb7fb6df69841b0955cdaa589a6bea8211f1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 8 Sep 2025 15:41:27 +0200 Subject: [PATCH 011/145] feature(spaces) : start introducing SpaceScreen --- features/space/api/build.gradle.kts | 18 ++ .../features/space/api/SpaceEntryPoint.kt | 38 ++++ features/space/impl/build.gradle.kts | 57 ++++++ .../space/impl/DefaultSpaceEntryPoint.kt | 39 ++++ .../features/space/impl/SpaceEvents.kt | 12 ++ .../android/features/space/impl/SpaceNode.kt | 39 ++++ .../features/space/impl/SpacePresenter.kt | 55 ++++++ .../android/features/space/impl/SpaceState.kt | 21 +++ .../features/space/impl/SpaceStateProvider.kt | 25 +++ .../android/features/space/impl/SpaceView.kt | 177 ++++++++++++++++++ .../matrix/api/spaces/SpaceService.kt | 4 +- .../matrix/impl/spaces/RustSpaceService.kt | 5 +- 12 files changed, 486 insertions(+), 4 deletions(-) create mode 100644 features/space/api/build.gradle.kts create mode 100644 features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt create mode 100644 features/space/impl/build.gradle.kts create mode 100644 features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt create mode 100644 features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceEvents.kt create mode 100644 features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt create mode 100644 features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt create mode 100644 features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceState.kt create mode 100644 features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt create mode 100644 features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt diff --git a/features/space/api/build.gradle.kts b/features/space/api/build.gradle.kts new file mode 100644 index 0000000000..b9a7f3226e --- /dev/null +++ b/features/space/api/build.gradle.kts @@ -0,0 +1,18 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.features.space.api" +} + +dependencies { + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) +} diff --git a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt new file mode 100644 index 0000000000..813450d7cb --- /dev/null +++ b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.space.api + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import io.element.android.libraries.architecture.FeatureEntryPoint +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias +import io.element.android.libraries.matrix.api.spaces.SpaceRoom + +interface SpaceEntryPoint : FeatureEntryPoint { + fun nodeBuilder( + parentNode: Node, + buildContext: BuildContext, + ): NodeBuilder + + interface NodeBuilder { + fun params(params: Params): NodeBuilder + fun callback(callback: Callback): NodeBuilder + fun build(): Node + } + + sealed interface Params : Plugin { + data class Id(val roomId: RoomId) : Params + data class Full(val spaceRoom: SpaceRoom) : Params + } + + interface Callback : Plugin { + fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List) + } +} diff --git a/features/space/impl/build.gradle.kts b/features/space/impl/build.gradle.kts new file mode 100644 index 0000000000..5a397fa269 --- /dev/null +++ b/features/space/impl/build.gradle.kts @@ -0,0 +1,57 @@ +import extension.ComponentMergingStrategy +import extension.setupAnvil + +/* + * Copyright 2022-2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +plugins { + id("io.element.android-compose-library") + id("kotlin-parcelize") +} + +android { + namespace = "io.element.android.features.space.impl" + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } +} + +setupAnvil(componentMergingStrategy = ComponentMergingStrategy.KSP) + +dependencies { + implementation(projects.libraries.core) + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) + implementation(projects.libraries.matrixui) + implementation(projects.libraries.designsystem) + implementation(projects.libraries.uiStrings) + implementation(projects.libraries.androidutils) + implementation(projects.libraries.deeplink.api) + implementation(projects.services.analytics.api) + implementation(libs.coil.compose) + implementation(projects.libraries.featureflag.api) + implementation(projects.features.invite.api) + api(projects.features.space.api) + + testImplementation(libs.test.junit) + testImplementation(libs.test.mockk) + testImplementation(libs.coroutines.test) + testImplementation(libs.molecule.runtime) + testImplementation(libs.test.truth) + testImplementation(libs.test.turbine) + testImplementation(libs.test.robolectric) + testImplementation(projects.services.analytics.test) + testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.tests.testutils) + testImplementation(libs.androidx.compose.ui.test.junit) + testImplementation(projects.features.invite.test) + testReleaseImplementation(libs.androidx.compose.ui.test.manifest) +} diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt new file mode 100644 index 0000000000..9a0f10a15b --- /dev/null +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.space.impl + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.space.api.SpaceEntryPoint +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.SessionScope +import javax.inject.Inject + +@ContributesBinding(SessionScope::class) +class DefaultSpaceEntryPoint @Inject constructor() : SpaceEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): SpaceEntryPoint.NodeBuilder { + val plugins = mutableSetOf() + return object : SpaceEntryPoint.NodeBuilder { + override fun params(params: SpaceEntryPoint.Params): SpaceEntryPoint.NodeBuilder { + plugins.add(params) + return this + } + + override fun callback(callback: SpaceEntryPoint.Callback): SpaceEntryPoint.NodeBuilder { + plugins.add(callback) + return this + } + + override fun build(): Node { + return parentNode.createNode(buildContext, plugins = plugins.toList()) + } + } + } +} diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceEvents.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceEvents.kt new file mode 100644 index 0000000000..16a521f6dd --- /dev/null +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceEvents.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.space.impl + +sealed interface SpaceEvents { + +} diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt new file mode 100644 index 0000000000..950cfe17d7 --- /dev/null +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.space.impl + +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.features.space.api.SpaceEntryPoint +import io.element.android.libraries.di.SessionScope + +@ContributesNode(SessionScope::class) +class SpaceNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: SpacePresenter, +) : Node(buildContext, plugins = plugins) { + + val params = plugins.filterIsInstance().single() + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + SpaceView( + state = state, + onBackClick = ::navigateUp, + modifier = modifier + ) + } +} diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt new file mode 100644 index 0000000000..b4a764b409 --- /dev/null +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.space.impl + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import io.element.android.features.invite.api.SeenInvitesStore +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.core.coroutine.mapState +import io.element.android.libraries.matrix.api.MatrixClient +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.persistentSetOf +import kotlinx.collections.immutable.toPersistentList +import kotlinx.collections.immutable.toPersistentSet +import kotlinx.coroutines.flow.map +import javax.inject.Inject + +class SpacePresenter @Inject constructor( + private val client: MatrixClient, + private val seenInvitesStore: SeenInvitesStore, +) : Presenter { + + @Composable + override fun present(): SpaceState { + val hideInvitesAvatar by remember { + client + .mediaPreviewService() + .mediaPreviewConfigFlow + .mapState { config -> config.hideInviteAvatar } + }.collectAsState() + val spaceRooms by client.spaceService.spaceRoomsFlow.collectAsState(emptyList()) + val seenSpaceInvites by remember { + seenInvitesStore.seenRoomIds().map { it.toPersistentSet() } + }.collectAsState(persistentSetOf()) + + fun handleEvents(event: SpaceEvents) { + //when (event) { } + } + + return SpaceState( + parentSpace = null, + children = spaceRooms.toPersistentList(), + seenSpaceInvites = seenSpaceInvites, + hideInvitesAvatar = hideInvitesAvatar, + eventSink = ::handleEvents, + ) + } +} diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceState.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceState.kt new file mode 100644 index 0000000000..ad3913af3d --- /dev/null +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceState.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.space.impl + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.ImmutableSet + +data class SpaceState( + val parentSpace: SpaceRoom?, + val children: ImmutableList, + val seenSpaceInvites: ImmutableSet, + val hideInvitesAvatar: Boolean, + val eventSink: (SpaceEvents) -> Unit +) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt new file mode 100644 index 0000000000..b5cb3e9546 --- /dev/null +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.space.impl + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import kotlinx.collections.immutable.persistentListOf + +open class SpaceStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aSpaceState(), + // Add other states here + ) +} + +fun aSpaceState() = SpaceState( + parentSpace = null, + children = persistentListOf(), + eventSink = {} +) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt new file mode 100644 index 0000000000..d1774d98bf --- /dev/null +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt @@ -0,0 +1,177 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.space.impl + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.heading +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.font.FontStyle +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.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.AvatarType +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.Text +import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import io.element.android.libraries.matrix.ui.components.SpaceHeaderRootView +import io.element.android.libraries.matrix.ui.components.SpaceHeaderView +import io.element.android.libraries.matrix.ui.components.SpaceRoomItemView +import io.element.android.libraries.matrix.ui.model.getAvatarData +import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.toImmutableList + +@Composable +fun SpaceView( + state: SpaceState, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Scaffold( + modifier = modifier, + contentWindowInsets = WindowInsets.statusBars, + topBar = { + SpaceViewTopBar(spaceRoom = null, onBackClick = onBackClick) + }, + content = { padding -> + Box( + modifier = Modifier + .padding(padding) + .consumeWindowInsets(padding) + ) { + SpaceViewContent(state) + } + }, + ) +} + + +@Composable +private fun SpaceViewContent( + state: SpaceState, + modifier: Modifier = Modifier, +){ + LazyColumn(modifier) { + val parentSpace = state.parentSpace + if (parentSpace != null) { + item { + SpaceHeaderView( + avatarData = parentSpace.getAvatarData(AvatarSize.SpaceHeader), + name = parentSpace.name, + topic = parentSpace.topic, + joinRule = parentSpace.joinRule, + heroes = parentSpace.heroes.toImmutableList(), + numberOfMembers = parentSpace.numJoinedMembers, + numberOfRooms = parentSpace.childrenCount, + ) + } + } + state.children.forEach { + item(it.roomId) { + val isInvitation = it.state == CurrentUserMembership.INVITED + SpaceRoomItemView( + spaceRoom = it, + showUnreadIndicator = isInvitation && it.roomId !in state.seenSpaceInvites, + hideAvatars = isInvitation && state.hideInvitesAvatar, + onClick = { + + }, + onLongClick = { + + } + ) + } + } + } +} + + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun SpaceViewTopBar( + spaceRoom: SpaceRoom?, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + TopAppBar( + modifier = modifier, + navigationIcon = { + BackButton(onClick = onBackClick) + }, + title = { + if (spaceRoom != null) { + SpaceAvatarAndNameRow( + name = spaceRoom.name, + avatarData = spaceRoom.getAvatarData(AvatarSize.TimelineRoom), + ) + } + }, + actions = { + }, + windowInsets = WindowInsets(0.dp) + ) +} + +@Composable +private fun SpaceAvatarAndNameRow( + name: String?, + avatarData: AvatarData, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically + ) { + Avatar( + avatarData = avatarData, + avatarType = AvatarType.Space(), + ) + Text( + modifier = Modifier + .padding(horizontal = 8.dp) + .semantics { + heading() + }, + text = name ?: stringResource(CommonStrings.common_no_room_name), + style = ElementTheme.typography.fontBodyLgMedium, + fontStyle = FontStyle.Italic.takeIf { name == null }, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } +} + +@PreviewsDayNight +@Composable +internal fun SpaceViewPreview( + @PreviewParameter(SpaceStateProvider::class) state: SpaceState +) = ElementPreview { + SpaceView( + state = state, + onBackClick = {}, + ) +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt index 917369a6a7..22f78bf780 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt @@ -7,12 +7,12 @@ package io.element.android.libraries.matrix.api.spaces -import io.element.android.libraries.matrix.api.core.SpaceId +import io.element.android.libraries.matrix.api.core.RoomId import kotlinx.coroutines.flow.SharedFlow interface SpaceService { val spaceRoomsFlow: SharedFlow> suspend fun joinedSpaces(): Result> - suspend fun spaceRoomList(spaceId: SpaceId): SpaceRoomList + suspend fun spaceRoomList(id: RoomId): SpaceRoomList } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt index 4d26040021..da4f62ad0c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.matrix.impl.spaces import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.api.spaces.SpaceRoomList @@ -50,8 +51,8 @@ class RustSpaceService( } } - override suspend fun spaceRoomList(spaceId: SpaceId): SpaceRoomList { - val innerSpaceRoomList = innerSpaceService.spaceRoomList(spaceId.value) + override suspend fun spaceRoomList(id: RoomId): SpaceRoomList { + val innerSpaceRoomList = innerSpaceService.spaceRoomList(id.value) return RustSpaceRoomList( inner = innerSpaceRoomList, sessionCoroutineScope = sessionCoroutineScope, From b45a4c3b2cec710eb5fab79a88960136275818ed Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 8 Sep 2025 21:57:25 +0200 Subject: [PATCH 012/145] feature (space) : iterate on space list (and space screen) --- .../android/appnav/room/RoomFlowNode.kt | 26 ++++++------ .../android/features/home/impl/HomeView.kt | 2 +- .../home/impl/spaces/HomeSpacesView.kt | 12 +++--- .../features/space/api/SpaceEntryPoint.kt | 7 ++++ .../android/features/space/impl/SpaceNode.kt | 3 +- .../features/space/impl/SpacePresenter.kt | 22 +++++++--- .../android/features/space/impl/SpaceView.kt | 1 - .../matrix/api/spaces/SpaceService.kt | 2 +- .../matrix/impl/spaces/RustSpaceRoomList.kt | 40 ++++++++++++------- .../matrix/impl/spaces/RustSpaceService.kt | 5 +-- .../impl/spaces/SpaceRoomListExtensions.kt | 3 ++ 11 files changed, 79 insertions(+), 44 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt index 12d9df78cf..c6381d4c7d 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt @@ -30,7 +30,9 @@ import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode import io.element.android.appnav.room.joined.LoadingRoomNodeView import io.element.android.features.joinroom.api.JoinRoomEntryPoint import io.element.android.features.roomaliasesolver.api.RoomAliasResolverEntryPoint +import io.element.android.features.roomaliasesolver.api.RoomAliasResolverEntryPoint.Params import io.element.android.features.roomdirectory.api.RoomDescription +import io.element.android.features.space.api.SpaceEntryPoint import io.element.android.libraries.architecture.BackstackView import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.NodeInputs @@ -43,6 +45,7 @@ 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.SpaceId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias @@ -72,6 +75,7 @@ class RoomFlowNode( private val roomAliasResolverEntryPoint: RoomAliasResolverEntryPoint, private val syncService: SyncService, private val membershipObserver: RoomMembershipObserver, + private val spaceEntryPoint: SpaceEntryPoint, ) : BaseFlowNode( backstack = BackStack( initialElement = NavTarget.Loading, @@ -106,6 +110,9 @@ class RoomFlowNode( @Parcelize data class JoinedRoom(val roomId: RoomId) : NavTarget + + @Parcelize + data class Space(val spaceId: RoomId) : NavTarget } override fun onBuilt() { @@ -146,17 +153,7 @@ class RoomFlowNode( when (membership) { CurrentUserMembership.JOINED -> { if (isSpace) { - // It should not happen, but probably due to an issue in the sliding sync, - // we can have a space here in case the space has just been joined. - // So navigate to the JoinRoom target for now, which will - // handle the space not supported screen - backstack.newRoot( - NavTarget.JoinRoom( - roomId = roomId, - serverNames = serverNames, - trigger = inputs.trigger.getOrNull() ?: JoinedRoom.Trigger.Invite, - ) - ) + backstack.newRoot(NavTarget.Space(spaceId = roomId)) } else { backstack.newRoot(NavTarget.JoinedRoom(roomId)) } @@ -194,7 +191,7 @@ class RoomFlowNode( ) } } - val params = RoomAliasResolverEntryPoint.Params(navTarget.roomAlias) + val params = Params(navTarget.roomAlias) roomAliasResolverEntryPoint.nodeBuilder(this, buildContext) .callback(callback) .params(params) @@ -218,6 +215,11 @@ class RoomFlowNode( ) createNode(buildContext, plugins = listOf(inputs) + roomFlowNodeCallback) } + is NavTarget.Space -> { + spaceEntryPoint.nodeBuilder(this, buildContext) + .params(SpaceEntryPoint.Params.Id(navTarget.spaceId)) + .build() + } } } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt index 6d531504ab..37727712fb 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt @@ -269,7 +269,7 @@ private fun HomeScaffold( .hazeSource(state = hazeState), state = state.homeSpacesState, onSpaceClick = { spaceId -> - // TODO + onRoomClick(spaceId) } ) } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt index cb93b297be..51dac2e0a3 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt @@ -52,15 +52,15 @@ fun HomeSpacesView( ) } } - state.spaceRooms.forEach { - item(it.roomId) { - val isInvitation = it.state == CurrentUserMembership.INVITED + state.spaceRooms.forEach { spaceRoom -> + item(spaceRoom.roomId) { + val isInvitation = spaceRoom.state == CurrentUserMembership.INVITED SpaceRoomItemView( - spaceRoom = it, - showUnreadIndicator = isInvitation && it.roomId !in state.seenSpaceInvites, + spaceRoom = spaceRoom, + showUnreadIndicator = isInvitation && spaceRoom.roomId !in state.seenSpaceInvites, hideAvatars = isInvitation && state.hideInvitesAvatar, onClick = { - onSpaceClick(it.roomId) + onSpaceClick(spaceRoom.roomId) }, onLongClick = { diff --git a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt index 813450d7cb..6a7002af2f 100644 --- a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt +++ b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt @@ -30,6 +30,13 @@ interface SpaceEntryPoint : FeatureEntryPoint { sealed interface Params : Plugin { data class Id(val roomId: RoomId) : Params data class Full(val spaceRoom: SpaceRoom) : Params + + fun roomId(): RoomId { + return when (this) { + is Id -> roomId + is Full -> spaceRoom.roomId + } + } } interface Callback : Plugin { diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt index 950cfe17d7..870b9b139c 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt @@ -22,10 +22,11 @@ import io.element.android.libraries.di.SessionScope class SpaceNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val presenter: SpacePresenter, + private val presenterFactory: SpacePresenter.Factory, ) : Node(buildContext, plugins = plugins) { val params = plugins.filterIsInstance().single() + private val presenter = presenterFactory.create(params) @Composable override fun View(modifier: Modifier) { diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt index b4a764b409..7e1c12ca87 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt @@ -11,22 +11,33 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.Inject import io.element.android.features.invite.api.SeenInvitesStore +import io.element.android.features.space.api.SpaceEntryPoint import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.matrix.api.MatrixClient -import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentSet import kotlinx.coroutines.flow.map -import javax.inject.Inject -class SpacePresenter @Inject constructor( +@Inject +class SpacePresenter( + @Assisted private val params: SpaceEntryPoint.Params, private val client: MatrixClient, private val seenInvitesStore: SeenInvitesStore, ) : Presenter { + @AssistedFactory + interface Factory { + fun create(params: SpaceEntryPoint.Params): SpacePresenter + } + + private val spaceRoomList = client.spaceService.spaceRoomList(params.roomId()) + @Composable override fun present(): SpaceState { val hideInvitesAvatar by remember { @@ -35,18 +46,19 @@ class SpacePresenter @Inject constructor( .mediaPreviewConfigFlow .mapState { config -> config.hideInviteAvatar } }.collectAsState() - val spaceRooms by client.spaceService.spaceRoomsFlow.collectAsState(emptyList()) val seenSpaceInvites by remember { seenInvitesStore.seenRoomIds().map { it.toPersistentSet() } }.collectAsState(persistentSetOf()) + val children by spaceRoomList.spaceRoomsFlow.collectAsState(emptyList()) + fun handleEvents(event: SpaceEvents) { //when (event) { } } return SpaceState( parentSpace = null, - children = spaceRooms.toPersistentList(), + children = children.toPersistentList(), seenSpaceInvites = seenSpaceInvites, hideInvitesAvatar = hideInvitesAvatar, eventSink = ::handleEvents, diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt index d1774d98bf..d7d03974da 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt @@ -132,7 +132,6 @@ private fun SpaceViewTopBar( }, actions = { }, - windowInsets = WindowInsets(0.dp) ) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt index 22f78bf780..b4572ad0bb 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceService.kt @@ -14,5 +14,5 @@ interface SpaceService { val spaceRoomsFlow: SharedFlow> suspend fun joinedSpaces(): Result> - suspend fun spaceRoomList(id: RoomId): SpaceRoomList + fun spaceRoomList(id: RoomId): SpaceRoomList } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt index efe405714e..9691f63c12 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt @@ -10,40 +10,52 @@ package io.element.android.libraries.matrix.impl.spaces import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.api.spaces.SpaceRoomList +import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList class RustSpaceRoomList( - private val inner: InnerSpaceRoomList, + private val innerProvider: suspend () -> InnerSpaceRoomList, sessionCoroutineScope: CoroutineScope, spaceRoomMapper: SpaceRoomMapper, ) : SpaceRoomList { + + private val inner = CompletableDeferred() override val spaceRoomsFlow = MutableSharedFlow>(replay = 1, extraBufferCapacity = Int.MAX_VALUE) - override val paginationStatusFlow = MutableStateFlow(inner.paginationState().into()) + override val paginationStatusFlow: MutableStateFlow = + MutableStateFlow(SpaceRoomList.PaginationStatus.Idle(hasMoreToLoad = false)) private val spaceListUpdateProcessor = SpaceListUpdateProcessor(spaceRoomsFlow, spaceRoomMapper) init { - inner.paginationStateFlow() - .onEach { paginationStatus -> - paginationStatusFlow.emit(paginationStatus.into()) - } - .launchIn(sessionCoroutineScope) + sessionCoroutineScope.launch { + inner.complete(innerProvider()) + } + sessionCoroutineScope.launch { + inner.await().paginationStateFlow() + .onEach { paginationStatus -> + paginationStatusFlow.emit(paginationStatus.into()) + } + .collect() + } - inner.spaceListUpdateFlow() - .onEach { updates -> - spaceListUpdateProcessor.postUpdates(updates) - } - .launchIn(sessionCoroutineScope) + sessionCoroutineScope.launch { + inner.await().spaceListUpdateFlow() + .onEach { updates -> + spaceListUpdateProcessor.postUpdates(updates) + } + .collect() + } } override suspend fun paginate(): Result { return runCatchingExceptions { - inner.paginate() + inner.await().paginate() } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt index da4f62ad0c..3e8fd77843 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt @@ -51,10 +51,9 @@ class RustSpaceService( } } - override suspend fun spaceRoomList(id: RoomId): SpaceRoomList { - val innerSpaceRoomList = innerSpaceService.spaceRoomList(id.value) + override fun spaceRoomList(id: RoomId): SpaceRoomList { return RustSpaceRoomList( - inner = innerSpaceRoomList, + innerProvider = { innerSpaceService.spaceRoomList(id.value) }, sessionCoroutineScope = sessionCoroutineScope, spaceRoomMapper = spaceRoomMapper ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomListExtensions.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomListExtensions.kt index 4976f37117..3d1a002e4d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomListExtensions.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomListExtensions.kt @@ -28,6 +28,9 @@ internal fun SpaceRoomListInterface.paginationStateFlow(): Flow Date: Wed, 10 Sep 2025 10:48:34 +0200 Subject: [PATCH 013/145] feature (space) : add space cache and navigation to sub space/room --- .../android/appnav/LoggedInFlowNode.kt | 10 ++- .../android/appnav/room/RoomFlowNode.kt | 5 +- features/home/impl/build.gradle.kts | 1 + .../impl/spaces/HomeSpacesStateProvider.kt | 1 + .../home/impl/spaces/SpaceRoomProvider.kt | 35 +------- .../features/space/api/SpaceEntryPoint.kt | 20 ++--- features/space/impl/build.gradle.kts | 1 + .../space/impl/DefaultSpaceEntryPoint.kt | 4 +- .../features/space/impl/SpaceEvents.kt | 2 +- .../android/features/space/impl/SpaceNode.kt | 10 ++- .../features/space/impl/SpacePresenter.kt | 39 +++++++-- .../android/features/space/impl/SpaceState.kt | 3 +- .../features/space/impl/SpaceStateProvider.kt | 43 +++++++++- .../android/features/space/impl/SpaceView.kt | 83 +++++++++++++------ .../matrix/api/spaces/SpaceRoomList.kt | 2 + .../matrix/impl/spaces/RustSpaceRoomList.kt | 15 +++- .../matrix/impl/spaces/RustSpaceService.kt | 11 ++- .../impl/spaces/SpaceListUpdateProcessor.kt | 4 +- .../matrix/impl/spaces/SpaceRoomCache.kt | 44 ++++++++++ .../previewutils/room/SpaceRoomFixture.kt | 46 ++++++++++ 20 files changed, 278 insertions(+), 101 deletions(-) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt create mode 100644 libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index 2d08d5f6f5..97fff8ee5c 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -60,6 +60,7 @@ import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.features.roomdirectory.api.RoomDirectoryEntryPoint import io.element.android.features.securebackup.api.SecureBackupEntryPoint import io.element.android.features.share.api.ShareEntryPoint +import io.element.android.features.space.api.SpaceEntryPoint import io.element.android.features.startchat.api.StartChatEntryPoint import io.element.android.features.userprofile.api.UserProfileEntryPoint import io.element.android.features.verifysession.api.IncomingVerificationEntryPoint @@ -334,7 +335,7 @@ class LoggedInFlowNode( .build() } is NavTarget.Room -> { - val callback = object : JoinedRoomLoadedFlowNode.Callback { + val joinedRoomCallback = object : JoinedRoomLoadedFlowNode.Callback { override fun onOpenRoom(roomId: RoomId, serverNames: List) { backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias(), serverNames)) } @@ -373,6 +374,11 @@ class LoggedInFlowNode( backstack.push(NavTarget.Settings(PreferencesEntryPoint.InitialTarget.NotificationSettings)) } } + val spaceCallback = object : SpaceEntryPoint.Callback { + override fun onOpenRoom(roomId: RoomId) { + backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias())) + } + } val inputs = RoomFlowNode.Inputs( roomIdOrAlias = navTarget.roomIdOrAlias, roomDescription = Optional.ofNullable(navTarget.roomDescription), @@ -380,7 +386,7 @@ class LoggedInFlowNode( trigger = Optional.ofNullable(navTarget.trigger), initialElement = navTarget.initialElement ) - createNode(buildContext, plugins = listOf(inputs, callback)) + createNode(buildContext, plugins = listOf(inputs, joinedRoomCallback, spaceCallback)) } is NavTarget.UserProfile -> { val callback = object : UserProfileEntryPoint.Callback { diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt index c6381d4c7d..f2df6ee8c9 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt @@ -45,7 +45,6 @@ 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.SpaceId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias @@ -216,8 +215,10 @@ class RoomFlowNode( createNode(buildContext, plugins = listOf(inputs) + roomFlowNodeCallback) } is NavTarget.Space -> { + val spaceCallback = plugins().single() spaceEntryPoint.nodeBuilder(this, buildContext) - .params(SpaceEntryPoint.Params.Id(navTarget.spaceId)) + .inputs(SpaceEntryPoint.Inputs(roomId = navTarget.spaceId)) + .callback(spaceCallback) .build() } } diff --git a/features/home/impl/build.gradle.kts b/features/home/impl/build.gradle.kts index 57fefaf413..f0ebe6c02d 100644 --- a/features/home/impl/build.gradle.kts +++ b/features/home/impl/build.gradle.kts @@ -55,6 +55,7 @@ dependencies { implementation(libs.haze.materials) implementation(projects.features.reportroom.api) implementation(projects.features.changeroommemberroles.api) + implementation(projects.libraries.previewutils) api(projects.features.home.api) testImplementation(libs.androidx.compose.ui.test.junit) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt index 1aedc0ef19..921c340886 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt @@ -10,6 +10,7 @@ package io.element.android.features.home.impl.spaces import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import io.element.android.libraries.previewutils.room.aSpaceRoom import kotlinx.collections.immutable.toImmutableSet open class HomeSpacesStateProvider : PreviewParameterProvider { diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/SpaceRoomProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/SpaceRoomProvider.kt index 88c3c5799a..474e08293a 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/SpaceRoomProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/SpaceRoomProvider.kt @@ -8,13 +8,10 @@ package io.element.android.features.home.impl.spaces import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership -import io.element.android.libraries.matrix.api.room.RoomType -import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.spaces.SpaceRoom -import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.previewutils.room.aSpaceRoom class SpaceRoomProvider : PreviewParameterProvider { override val values: Sequence = sequenceOf( @@ -52,33 +49,3 @@ class SpaceRoomProvider : PreviewParameterProvider { ), ) } - -fun aSpaceRoom( - name: String? = "Space name", - avatarUrl: String? = null, - canonicalAlias: RoomAlias? = null, - childrenCount: Int = 0, - guestCanJoin: Boolean = false, - heroes: List = emptyList(), - joinRule: JoinRule? = null, - numJoinedMembers: Int = 0, - roomId: RoomId = RoomId("!roomId:example.com"), - roomType: RoomType = RoomType.Space, - state: CurrentUserMembership? = null, - topic: String? = null, - worldReadable: Boolean = false, -) = SpaceRoom( - name = name, - avatarUrl = avatarUrl, - canonicalAlias = canonicalAlias, - childrenCount = childrenCount, - guestCanJoin = guestCanJoin, - heroes = heroes, - joinRule = joinRule, - numJoinedMembers = numJoinedMembers, - roomId = roomId, - roomType = roomType, - state = state, - topic = topic, - worldReadable = worldReadable -) diff --git a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt index 6a7002af2f..cc298de601 100644 --- a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt +++ b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt @@ -12,8 +12,6 @@ import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import io.element.android.libraries.architecture.FeatureEntryPoint import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.RoomIdOrAlias -import io.element.android.libraries.matrix.api.spaces.SpaceRoom interface SpaceEntryPoint : FeatureEntryPoint { fun nodeBuilder( @@ -22,24 +20,16 @@ interface SpaceEntryPoint : FeatureEntryPoint { ): NodeBuilder interface NodeBuilder { - fun params(params: Params): NodeBuilder + fun inputs(inputs: Inputs): NodeBuilder fun callback(callback: Callback): NodeBuilder fun build(): Node } - sealed interface Params : Plugin { - data class Id(val roomId: RoomId) : Params - data class Full(val spaceRoom: SpaceRoom) : Params - - fun roomId(): RoomId { - return when (this) { - is Id -> roomId - is Full -> spaceRoom.roomId - } - } - } + data class Inputs( + val roomId: RoomId + ) : Plugin interface Callback : Plugin { - fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List) + fun onOpenRoom(roomId: RoomId) } } diff --git a/features/space/impl/build.gradle.kts b/features/space/impl/build.gradle.kts index 5a397fa269..5731b4a819 100644 --- a/features/space/impl/build.gradle.kts +++ b/features/space/impl/build.gradle.kts @@ -38,6 +38,7 @@ dependencies { implementation(libs.coil.compose) implementation(projects.libraries.featureflag.api) implementation(projects.features.invite.api) + implementation(projects.libraries.previewutils) api(projects.features.space.api) testImplementation(libs.test.junit) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt index 9a0f10a15b..22988a6964 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt @@ -21,8 +21,8 @@ class DefaultSpaceEntryPoint @Inject constructor() : SpaceEntryPoint { override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): SpaceEntryPoint.NodeBuilder { val plugins = mutableSetOf() return object : SpaceEntryPoint.NodeBuilder { - override fun params(params: SpaceEntryPoint.Params): SpaceEntryPoint.NodeBuilder { - plugins.add(params) + override fun inputs(inputs: SpaceEntryPoint.Inputs): SpaceEntryPoint.NodeBuilder { + plugins.add(inputs) return this } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceEvents.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceEvents.kt index 16a521f6dd..848dac3ebc 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceEvents.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceEvents.kt @@ -8,5 +8,5 @@ package io.element.android.features.space.impl sealed interface SpaceEvents { - + data object LoadMore : SpaceEvents } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt index 870b9b139c..c89e7d0aad 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt @@ -22,11 +22,12 @@ import io.element.android.libraries.di.SessionScope class SpaceNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val presenterFactory: SpacePresenter.Factory, + presenterFactory: SpacePresenter.Factory, ) : Node(buildContext, plugins = plugins) { - val params = plugins.filterIsInstance().single() - private val presenter = presenterFactory.create(params) + val inputs = plugins.filterIsInstance().single() + val callback = plugins.filterIsInstance().single() + private val presenter = presenterFactory.create(inputs) @Composable override fun View(modifier: Modifier) { @@ -34,6 +35,9 @@ class SpaceNode @AssistedInject constructor( SpaceView( state = state, onBackClick = ::navigateUp, + onRoomClick = { roomId -> + callback.onOpenRoom(roomId) + }, modifier = modifier ) } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt index 7e1c12ca87..5efc207430 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt @@ -8,9 +8,11 @@ package io.element.android.features.space.impl import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.Inject @@ -19,27 +21,35 @@ import io.element.android.features.space.api.SpaceEntryPoint import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.spaces.SpaceRoomList import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentSet +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch @Inject class SpacePresenter( - @Assisted private val params: SpaceEntryPoint.Params, + @Assisted private val inputs: SpaceEntryPoint.Inputs, private val client: MatrixClient, private val seenInvitesStore: SeenInvitesStore, ) : Presenter { @AssistedFactory interface Factory { - fun create(params: SpaceEntryPoint.Params): SpacePresenter + fun create(inputs: SpaceEntryPoint.Inputs): SpacePresenter } - private val spaceRoomList = client.spaceService.spaceRoomList(params.roomId()) + private val spaceRoomList = client.spaceService.spaceRoomList(inputs.roomId) @Composable override fun present(): SpaceState { + + LaunchedEffect(Unit) { + paginate() + } + val hideInvitesAvatar by remember { client .mediaPreviewService() @@ -50,18 +60,35 @@ class SpacePresenter( seenInvitesStore.seenRoomIds().map { it.toPersistentSet() } }.collectAsState(persistentSetOf()) + val coroutineScope = rememberCoroutineScope() val children by spaceRoomList.spaceRoomsFlow.collectAsState(emptyList()) + val hasMoreToLoad by remember { + spaceRoomList.paginationStatusFlow.mapState { status -> + when (status) { + is SpaceRoomList.PaginationStatus.Idle -> status.hasMoreToLoad + SpaceRoomList.PaginationStatus.Loading -> true + } + } + }.collectAsState() + + val currentSpace by remember { spaceRoomList.currentSpaceFlow() }.collectAsState(null) fun handleEvents(event: SpaceEvents) { - //when (event) { } + when (event) { + SpaceEvents.LoadMore -> coroutineScope.paginate() + } } - return SpaceState( - parentSpace = null, + currentSpace = currentSpace, children = children.toPersistentList(), seenSpaceInvites = seenSpaceInvites, hideInvitesAvatar = hideInvitesAvatar, + hasMoreToLoad = hasMoreToLoad, eventSink = ::handleEvents, ) } + + private fun CoroutineScope.paginate() = launch { + spaceRoomList.paginate() + } } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceState.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceState.kt index ad3913af3d..ad822283ca 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceState.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceState.kt @@ -13,9 +13,10 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableSet data class SpaceState( - val parentSpace: SpaceRoom?, + val currentSpace: SpaceRoom?, val children: ImmutableList, val seenSpaceInvites: ImmutableSet, val hideInvitesAvatar: Boolean, + val hasMoreToLoad: Boolean, val eventSink: (SpaceEvents) -> Unit ) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt index b5cb3e9546..36c2ab62b0 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt @@ -8,18 +8,53 @@ package io.element.android.features.space.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import kotlinx.collections.immutable.persistentListOf +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import io.element.android.libraries.previewutils.room.aSpaceRoom +import kotlinx.collections.immutable.toImmutableList +import kotlinx.collections.immutable.toImmutableSet open class SpaceStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aSpaceState(), + aSpaceState(hasMoreToLoad = true), + aSpaceState( + hasMoreToLoad = true, + children = aListOfSpaceRooms(), + ), + aSpaceState( + hasMoreToLoad = false, + children = aListOfSpaceRooms() + ) // Add other states here ) } -fun aSpaceState() = SpaceState( - parentSpace = null, - children = persistentListOf(), +fun aSpaceState( + parentSpace: SpaceRoom? = aSpaceRoom( + numJoinedMembers = 5, + childrenCount = 10, + worldReadable = true, + roomId = RoomId("!spaceId0:example.com"), + ), + children: List = emptyList(), + seenSpaceInvites: Set = emptySet(), + hideInvitesAvatar: Boolean = false, + hasMoreToLoad: Boolean = false, +) = SpaceState( + currentSpace = parentSpace, + children = children.toImmutableList(), + seenSpaceInvites = seenSpaceInvites.toImmutableSet(), + hideInvitesAvatar = hideInvitesAvatar, + hasMoreToLoad = hasMoreToLoad, eventSink = {} ) + +private fun aListOfSpaceRooms(): List { + return listOf( + aSpaceRoom(roomId = RoomId("!spaceId0:example.com")), + aSpaceRoom(roomId = RoomId("!spaceId1:example.com")), + aSpaceRoom(roomId = RoomId("!spaceId2:example.com")), + ) +} diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt index d7d03974da..b6077f4007 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt @@ -9,13 +9,15 @@ package io.element.android.features.space.impl import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -33,12 +35,13 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType 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.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.spaces.SpaceRoom -import io.element.android.libraries.matrix.ui.components.SpaceHeaderRootView import io.element.android.libraries.matrix.ui.components.SpaceHeaderView import io.element.android.libraries.matrix.ui.components.SpaceRoomItemView import io.element.android.libraries.matrix.ui.model.getAvatarData @@ -49,56 +52,57 @@ import kotlinx.collections.immutable.toImmutableList fun SpaceView( state: SpaceState, onBackClick: () -> Unit, + onRoomClick: (roomId: RoomId) -> Unit, modifier: Modifier = Modifier, ) { Scaffold( modifier = modifier, - contentWindowInsets = WindowInsets.statusBars, topBar = { SpaceViewTopBar(spaceRoom = null, onBackClick = onBackClick) }, content = { padding -> Box( - modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) + modifier = Modifier.padding(padding) ) { - SpaceViewContent(state) + SpaceViewContent( + state = state, + onRoomClick = onRoomClick + ) } }, ) } - @Composable private fun SpaceViewContent( state: SpaceState, + onRoomClick: (roomId: RoomId) -> Unit, modifier: Modifier = Modifier, -){ - LazyColumn(modifier) { - val parentSpace = state.parentSpace - if (parentSpace != null) { +) { + LazyColumn(modifier.fillMaxSize()) { + val currentSpace = state.currentSpace + if (currentSpace != null) { item { SpaceHeaderView( - avatarData = parentSpace.getAvatarData(AvatarSize.SpaceHeader), - name = parentSpace.name, - topic = parentSpace.topic, - joinRule = parentSpace.joinRule, - heroes = parentSpace.heroes.toImmutableList(), - numberOfMembers = parentSpace.numJoinedMembers, - numberOfRooms = parentSpace.childrenCount, + avatarData = currentSpace.getAvatarData(AvatarSize.SpaceHeader), + name = currentSpace.name, + topic = currentSpace.topic, + joinRule = currentSpace.joinRule, + heroes = currentSpace.heroes.toImmutableList(), + numberOfMembers = currentSpace.numJoinedMembers, + numberOfRooms = currentSpace.childrenCount, ) } } - state.children.forEach { - item(it.roomId) { - val isInvitation = it.state == CurrentUserMembership.INVITED + state.children.forEach { spaceRoom -> + item { + val isInvitation = spaceRoom.state == CurrentUserMembership.INVITED SpaceRoomItemView( - spaceRoom = it, - showUnreadIndicator = isInvitation && it.roomId !in state.seenSpaceInvites, + spaceRoom = spaceRoom, + showUnreadIndicator = isInvitation && spaceRoom.roomId !in state.seenSpaceInvites, hideAvatars = isInvitation && state.hideInvitesAvatar, onClick = { - + onRoomClick(spaceRoom.roomId) }, onLongClick = { @@ -106,9 +110,33 @@ private fun SpaceViewContent( ) } } + if (state.hasMoreToLoad) { + item { + LoadingMoreIndicator(eventSink = state.eventSink) + } + } } } +@Composable +private fun LoadingMoreIndicator( + eventSink: (SpaceEvents) -> Unit, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator( + strokeWidth = 2.dp, + modifier = Modifier.padding(vertical = 8.dp) + ) + val latestEventSink by rememberUpdatedState(eventSink) + LaunchedEffect(Unit) { + latestEventSink(SpaceEvents.LoadMore) + } + } +} @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -171,6 +199,7 @@ internal fun SpaceViewPreview( ) = ElementPreview { SpaceView( state = state, + onRoomClick = {}, onBackClick = {}, ) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt index a1f79cdb0b..0b4bb3eae8 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt @@ -16,6 +16,8 @@ interface SpaceRoomList { data class Idle(val hasMoreToLoad: Boolean) : PaginationStatus } + fun currentSpaceFlow(): Flow + val spaceRoomsFlow: Flow> val paginationStatusFlow: StateFlow suspend fun paginate(): Result diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt index 9691f63c12..29f226a730 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt @@ -8,10 +8,12 @@ package io.element.android.libraries.matrix.impl.spaces import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.api.spaces.SpaceRoomList import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.collect @@ -21,16 +23,27 @@ import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList class RustSpaceRoomList( + private val roomId: RoomId, private val innerProvider: suspend () -> InnerSpaceRoomList, sessionCoroutineScope: CoroutineScope, spaceRoomMapper: SpaceRoomMapper, + private val spaceRoomCache: SpaceRoomCache, ) : SpaceRoomList { private val inner = CompletableDeferred() + + override fun currentSpaceFlow(): Flow { + return spaceRoomCache.getSpaceRoomFlow(roomId) + } + override val spaceRoomsFlow = MutableSharedFlow>(replay = 1, extraBufferCapacity = Int.MAX_VALUE) override val paginationStatusFlow: MutableStateFlow = MutableStateFlow(SpaceRoomList.PaginationStatus.Idle(hasMoreToLoad = false)) - private val spaceListUpdateProcessor = SpaceListUpdateProcessor(spaceRoomsFlow, spaceRoomMapper) + private val spaceListUpdateProcessor = SpaceListUpdateProcessor( + spaceRoomsFlow = spaceRoomsFlow, + mapper = spaceRoomMapper, + spaceRoomCache = spaceRoomCache + ) init { sessionCoroutineScope.launch { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt index 3e8fd77843..58bacdd403 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt @@ -39,8 +39,13 @@ class RustSpaceService( private val sessionDispatcher: CoroutineDispatcher, ) : SpaceService { private val spaceRoomMapper = SpaceRoomMapper() + private val spaceRoomCache = SpaceRoomCache() override val spaceRoomsFlow = MutableSharedFlow>(replay = 1, extraBufferCapacity = 1) - private val spaceListUpdateProcessor = SpaceListUpdateProcessor(spaceRoomsFlow, spaceRoomMapper) + private val spaceListUpdateProcessor = SpaceListUpdateProcessor( + spaceRoomsFlow = spaceRoomsFlow, + mapper = spaceRoomMapper, + spaceRoomCache = spaceRoomCache + ) override suspend fun joinedSpaces(): Result> = withContext(sessionDispatcher) { runCatchingExceptions { @@ -53,9 +58,11 @@ class RustSpaceService( override fun spaceRoomList(id: RoomId): SpaceRoomList { return RustSpaceRoomList( + roomId = id, innerProvider = { innerSpaceService.spaceRoomList(id.value) }, sessionCoroutineScope = sessionCoroutineScope, - spaceRoomMapper = spaceRoomMapper + spaceRoomMapper = spaceRoomMapper, + spaceRoomCache = spaceRoomCache, ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt index a1f8584299..c968cc3edb 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt @@ -18,6 +18,7 @@ import timber.log.Timber internal class SpaceListUpdateProcessor( private val spaceRoomsFlow: MutableSharedFlow>, private val mapper: SpaceRoomMapper, + private val spaceRoomCache: SpaceRoomCache, ) { private val mutex = Mutex() @@ -36,7 +37,8 @@ internal class SpaceListUpdateProcessor( mutableListOf() } block(spaceRooms) - spaceRoomsFlow.tryEmit(spaceRooms) + spaceRoomCache.update(spaceRooms) + spaceRoomsFlow.emit(spaceRooms) } private fun MutableList.applyUpdate(update: SpaceListUpdate) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt new file mode 100644 index 0000000000..79868336de --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.spaces + +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock + +/** + * An in memory cache of space rooms. + * Only caches Rooms with roomType [io.element.android.libraries.matrix.api.room.RoomType.Space]. + */ +class SpaceRoomCache() { + private val inMemoryCache = MutableStateFlow>(LinkedHashMap()) + private val mutex = Mutex() + + fun getSpaceRoomFlow(roomId: RoomId): Flow { + return inMemoryCache.map { it[roomId] } + } + + suspend fun update(spaceRooms: List) = mutex.withLock { + inMemoryCache.update { cache -> + spaceRooms + .filter { it.isSpace } + .forEach { spaceRoom -> + cache.put(spaceRoom.roomId, spaceRoom) + } + cache + } + } +} diff --git a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt new file mode 100644 index 0000000000..3acea6255b --- /dev/null +++ b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.previewutils.room + +import io.element.android.libraries.matrix.api.core.RoomAlias +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.room.RoomType +import io.element.android.libraries.matrix.api.room.join.JoinRule +import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import io.element.android.libraries.matrix.api.user.MatrixUser + +fun aSpaceRoom( + name: String? = "Space name", + avatarUrl: String? = null, + canonicalAlias: RoomAlias? = null, + childrenCount: Int = 0, + guestCanJoin: Boolean = false, + heroes: List = emptyList(), + joinRule: JoinRule? = null, + numJoinedMembers: Int = 0, + roomId: RoomId = RoomId("!roomId:example.com"), + roomType: RoomType = RoomType.Space, + state: CurrentUserMembership? = null, + topic: String? = null, + worldReadable: Boolean = false, +) = SpaceRoom( + name = name, + avatarUrl = avatarUrl, + canonicalAlias = canonicalAlias, + childrenCount = childrenCount, + guestCanJoin = guestCanJoin, + heroes = heroes, + joinRule = joinRule, + numJoinedMembers = numJoinedMembers, + roomId = roomId, + roomType = roomType, + state = state, + topic = topic, + worldReadable = worldReadable +) From f5882fef1198b974b3b892970948dc2d2dd4bfbb Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 10 Sep 2025 12:04:09 +0200 Subject: [PATCH 014/145] feature (space) : display top bar title --- .../element/android/features/space/impl/SpaceView.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt index b6077f4007..0213f94c5b 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt @@ -58,7 +58,7 @@ fun SpaceView( Scaffold( modifier = modifier, topBar = { - SpaceViewTopBar(spaceRoom = null, onBackClick = onBackClick) + SpaceViewTopBar(currentSpace = state.currentSpace, onBackClick = onBackClick) }, content = { padding -> Box( @@ -141,7 +141,7 @@ private fun LoadingMoreIndicator( @OptIn(ExperimentalMaterial3Api::class) @Composable private fun SpaceViewTopBar( - spaceRoom: SpaceRoom?, + currentSpace: SpaceRoom?, onBackClick: () -> Unit, modifier: Modifier = Modifier, ) { @@ -151,10 +151,10 @@ private fun SpaceViewTopBar( BackButton(onClick = onBackClick) }, title = { - if (spaceRoom != null) { + if (currentSpace != null) { SpaceAvatarAndNameRow( - name = spaceRoom.name, - avatarData = spaceRoom.getAvatarData(AvatarSize.TimelineRoom), + name = currentSpace.name, + avatarData = currentSpace.getAvatarData(AvatarSize.TimelineRoom), ) } }, From bb39a9f3995c22f7f1986aa59a941f2f3bb8ad7b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Sep 2025 14:08:10 +0200 Subject: [PATCH 015/145] Code cleanup, remove dead code and fix compilation issue --- .../android/features/home/impl/spaces/HomeSpacesState.kt | 1 - .../android/features/home/impl/spaces/HomeSpacesView.kt | 2 +- .../android/features/invite/api/SeenInvitesStore.kt | 3 --- features/space/api/build.gradle.kts | 2 +- .../element/android/features/space/api/SpaceEntryPoint.kt | 2 +- features/space/impl/build.gradle.kts | 7 +++---- .../android/features/space/impl/DefaultSpaceEntryPoint.kt | 2 +- .../io/element/android/features/space/impl/SpaceNode.kt | 5 ++--- .../element/android/features/space/impl/SpacePresenter.kt | 3 --- .../io/element/android/features/space/impl/SpaceView.kt | 2 +- .../io/element/android/libraries/matrix/api/core/RoomId.kt | 2 -- .../android/libraries/matrix/api/spaces/SpaceRoomList.kt | 3 +-- .../libraries/matrix/impl/spaces/RustSpaceRoomList.kt | 1 - .../libraries/matrix/impl/spaces/RustSpaceService.kt | 1 - .../matrix/impl/spaces/SpaceListUpdateProcessor.kt | 4 +--- .../android/libraries/matrix/impl/spaces/SpaceRoomCache.kt | 5 +---- .../libraries/matrix/impl/spaces/SpaceRoomMapper.kt | 1 - 17 files changed, 13 insertions(+), 33 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt index 39871fb905..96733991f9 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt @@ -8,7 +8,6 @@ package io.element.android.features.home.impl.spaces import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.collections.immutable.ImmutableSet diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt index 51dac2e0a3..8b07b9f526 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt @@ -63,7 +63,7 @@ fun HomeSpacesView( onSpaceClick(spaceRoom.roomId) }, onLongClick = { - + // TODO } ) } diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt index 283deb78fb..682970ffe7 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt @@ -8,10 +8,7 @@ package io.element.android.features.invite.api import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.SpaceId -import io.element.android.libraries.matrix.api.core.toSpaceId import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map interface SeenInvitesStore { /** diff --git a/features/space/api/build.gradle.kts b/features/space/api/build.gradle.kts index b9a7f3226e..dd19efefec 100644 --- a/features/space/api/build.gradle.kts +++ b/features/space/api/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. diff --git a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt index cc298de601..88cbbad5dd 100644 --- a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt +++ b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. diff --git a/features/space/impl/build.gradle.kts b/features/space/impl/build.gradle.kts index 5731b4a819..b41f8ebc93 100644 --- a/features/space/impl/build.gradle.kts +++ b/features/space/impl/build.gradle.kts @@ -1,8 +1,7 @@ -import extension.ComponentMergingStrategy -import extension.setupAnvil +import extension.setupDependencyInjection /* - * Copyright 2022-2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. @@ -23,7 +22,7 @@ android { } } -setupAnvil(componentMergingStrategy = ComponentMergingStrategy.KSP) +setupDependencyInjection() dependencies { implementation(projects.libraries.core) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt index 22988a6964..a20e82f9a2 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt @@ -10,7 +10,7 @@ package io.element.android.features.space.impl import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin -import com.squareup.anvil.annotations.ContributesBinding +import dev.zacsweers.metro.ContributesBinding import io.element.android.features.space.api.SpaceEntryPoint import io.element.android.libraries.architecture.createNode import io.element.android.libraries.di.SessionScope diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt index c89e7d0aad..f826f9c499 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt @@ -24,9 +24,8 @@ class SpaceNode @AssistedInject constructor( @Assisted plugins: List, presenterFactory: SpacePresenter.Factory, ) : Node(buildContext, plugins = plugins) { - - val inputs = plugins.filterIsInstance().single() - val callback = plugins.filterIsInstance().single() + private val inputs = plugins.filterIsInstance().single() + private val callback = plugins.filterIsInstance().single() private val presenter = presenterFactory.create(inputs) @Composable diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt index 5efc207430..d06f1e8eb2 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt @@ -35,7 +35,6 @@ class SpacePresenter( private val client: MatrixClient, private val seenInvitesStore: SeenInvitesStore, ) : Presenter { - @AssistedFactory interface Factory { fun create(inputs: SpaceEntryPoint.Inputs): SpacePresenter @@ -45,11 +44,9 @@ class SpacePresenter( @Composable override fun present(): SpaceState { - LaunchedEffect(Unit) { paginate() } - val hideInvitesAvatar by remember { client .mediaPreviewService() diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt index 0213f94c5b..f3bdf7379b 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt @@ -105,7 +105,7 @@ private fun SpaceViewContent( onRoomClick(spaceRoom.roomId) }, onLongClick = { - + // TODO } ) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/RoomId.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/RoomId.kt index 1fab64020d..8d339ae704 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/RoomId.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/RoomId.kt @@ -20,5 +20,3 @@ value class RoomId(val value: String) : Serializable { override fun toString(): String = value } - -fun RoomId.toSpaceId(): SpaceId = SpaceId(this.value) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt index 0b4bb3eae8..a591fc2537 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. @@ -22,4 +22,3 @@ interface SpaceRoomList { val paginationStatusFlow: StateFlow suspend fun paginate(): Result } - diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt index 29f226a730..e3f2132a2f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt @@ -29,7 +29,6 @@ class RustSpaceRoomList( spaceRoomMapper: SpaceRoomMapper, private val spaceRoomCache: SpaceRoomCache, ) : SpaceRoomList { - private val inner = CompletableDeferred() override fun currentSpaceFlow(): Flow { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt index 58bacdd403..2a63367577 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceService.kt @@ -9,7 +9,6 @@ package io.element.android.libraries.matrix.impl.spaces import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.api.spaces.SpaceRoomList import io.element.android.libraries.matrix.api.spaces.SpaceService diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt index c968cc3edb..f1193661ea 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceListUpdateProcessor.kt @@ -44,9 +44,7 @@ internal class SpaceListUpdateProcessor( private fun MutableList.applyUpdate(update: SpaceListUpdate) { when (update) { is SpaceListUpdate.Append -> { - val newSpaces = update.values.map { it -> - it.let(mapper::map) - } + val newSpaces = update.values.map(mapper::map) addAll(newSpaces) } SpaceListUpdate.Clear -> clear() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt index 79868336de..63fe020ecd 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt @@ -7,9 +7,6 @@ package io.element.android.libraries.matrix.impl.spaces -import dev.zacsweers.metro.Inject -import dev.zacsweers.metro.SingleIn -import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.coroutines.flow.Flow @@ -23,7 +20,7 @@ import kotlinx.coroutines.sync.withLock * An in memory cache of space rooms. * Only caches Rooms with roomType [io.element.android.libraries.matrix.api.room.RoomType.Space]. */ -class SpaceRoomCache() { +class SpaceRoomCache { private val inMemoryCache = MutableStateFlow>(LinkedHashMap()) private val mutex = Mutex() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt index ade5063515..c217f941c7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt @@ -10,7 +10,6 @@ package io.element.android.libraries.matrix.impl.spaces import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.impl.room.join.map import io.element.android.libraries.matrix.impl.room.map From e2278853457f0a3be57ddd5503b2965cce47e4e0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Sep 2025 14:58:18 +0200 Subject: [PATCH 016/145] More compilation fixes. --- .../features/space/impl/DefaultSpaceEntryPoint.kt | 5 +++-- .../io/element/android/features/space/impl/SpaceNode.kt | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt index a20e82f9a2..1ef8275b27 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPoint.kt @@ -11,13 +11,14 @@ import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.Inject import io.element.android.features.space.api.SpaceEntryPoint import io.element.android.libraries.architecture.createNode import io.element.android.libraries.di.SessionScope -import javax.inject.Inject @ContributesBinding(SessionScope::class) -class DefaultSpaceEntryPoint @Inject constructor() : SpaceEntryPoint { +@Inject +class DefaultSpaceEntryPoint : SpaceEntryPoint { override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): SpaceEntryPoint.NodeBuilder { val plugins = mutableSetOf() return object : SpaceEntryPoint.NodeBuilder { diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt index f826f9c499..d37be4c76c 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt @@ -12,14 +12,15 @@ 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 dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.Inject +import io.element.android.annotations.ContributesNode import io.element.android.features.space.api.SpaceEntryPoint import io.element.android.libraries.di.SessionScope @ContributesNode(SessionScope::class) -class SpaceNode @AssistedInject constructor( +@Inject +class SpaceNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, presenterFactory: SpacePresenter.Factory, From 115e0e64f67c93e66fc22ef40bfbc0cd4bcad7c5 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 10 Sep 2025 13:17:52 +0000 Subject: [PATCH 017/145] Update screenshots --- .../features.home.impl.spaces_HomeSpaceItemView_Day_0_en.png | 3 --- .../features.home.impl.spaces_HomeSpaceItemView_Day_1_en.png | 3 --- .../features.home.impl.spaces_HomeSpaceItemView_Day_2_en.png | 3 --- .../features.home.impl.spaces_HomeSpaceItemView_Day_3_en.png | 3 --- .../features.home.impl.spaces_HomeSpaceItemView_Day_4_en.png | 3 --- ...features.home.impl.spaces_HomeSpaceItemView_Night_0_en.png | 3 --- ...features.home.impl.spaces_HomeSpaceItemView_Night_1_en.png | 3 --- ...features.home.impl.spaces_HomeSpaceItemView_Night_2_en.png | 3 --- ...features.home.impl.spaces_HomeSpaceItemView_Night_3_en.png | 3 --- ...features.home.impl.spaces_HomeSpaceItemView_Night_4_en.png | 3 --- .../features.home.impl.spaces_HomeSpacesView_Day_0_en.png | 4 ++-- .../features.home.impl.spaces_HomeSpacesView_Night_0_en.png | 4 ++-- .../images/features.space.impl_SpaceView_Day_0_en.png | 3 +++ .../images/features.space.impl_SpaceView_Day_1_en.png | 3 +++ .../images/features.space.impl_SpaceView_Day_2_en.png | 3 +++ .../images/features.space.impl_SpaceView_Day_3_en.png | 3 +++ .../images/features.space.impl_SpaceView_Night_0_en.png | 3 +++ .../images/features.space.impl_SpaceView_Night_1_en.png | 3 +++ .../images/features.space.impl_SpaceView_Night_2_en.png | 3 +++ .../images/features.space.impl_SpaceView_Night_3_en.png | 3 +++ 20 files changed, 28 insertions(+), 34 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_2_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_3_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_4_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_2_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_3_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_3_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_0_en.png deleted file mode 100644 index 4dc4712e67..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a241e70cffe61158784ac75425e13cd8d2695406f6e52a93ca7dddfdc9f99caa -size 14164 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_1_en.png deleted file mode 100644 index dc4f56f39b..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:864ab3319f7074643b58d2dd6da22a4c5493bae25502c89bf2c3503bc57cfe91 -size 11628 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_2_en.png deleted file mode 100644 index 403a96cbad..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ba93e44b8732d7bf78b25200a5db6e8a329f970aa1fb6a002033c9ebfd09b805 -size 11723 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_3_en.png deleted file mode 100644 index f12b559ded..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:59b6f98dc65ae4be92b7cdfde9778b390b6474205f75d48061d6345eece53675 -size 19034 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_4_en.png deleted file mode 100644 index 833415fba7..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Day_4_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b4a8cef8dc61dd71458d7518548e83f5e4484fd9dc740fefc690769ffbf6bd80 -size 18949 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_0_en.png deleted file mode 100644 index 175a0f0151..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7ce65c4dd01458194792d0a14eafc66e6e6f0a0e0f59259e4661322d0cf9a46d -size 13819 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_1_en.png deleted file mode 100644 index 443230a159..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3e3765e543cce879b97a35b8c3e1cdef4b6c9ce4b1739b9d9a544d6a56118399 -size 11414 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_2_en.png deleted file mode 100644 index 9ad249a00f..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:51b283fb8e976c8717abeef61dcf294f3efd52b7291fdf023c09759e6df6513d -size 11337 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_3_en.png deleted file mode 100644 index ceafbe6d6a..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c440b9628b8105b73f5f576c1b99269a74a89ab07f56080ad53cc888aca24da3 -size 18111 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_4_en.png deleted file mode 100644 index 3cf9c17cda..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpaceItemView_Night_4_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9ddecc15d26dbdd648ec7abbff51718da03326ebf32a2d675563110c096a198b -size 18141 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_0_en.png index bd804824f9..f36c5aa998 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dff393d500d855842d84d311b3bb5cb60bab6fc2e8e9efe3b593d675218d5024 -size 123012 +oid sha256:4053802814238aa74a5c606a4b37e0afcb923282c3e7cece737b0ec4f6828351 +size 106332 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_0_en.png index 6159775dd0..b77735afed 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9993c1937c780b4b7e3a47bfb53fa5735ac7bc20f29559281384ca32eb7c13ae -size 120701 +oid sha256:d02259f3163c49b5c39d38d7a84af50583f6a0ce2a66e8ad013ac18278de65c0 +size 103621 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_0_en.png new file mode 100644 index 0000000000..59cd1f1de1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e69f830b7f15de531fc46efc02964fb641a4e3754b5108fb8020e97bbfb4b56 +size 15698 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png new file mode 100644 index 0000000000..393434d50b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b5fba00f44ab63c07978ec0143f2f1fefc8fd1d78aed22a367e831c105b806c7 +size 17306 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_2_en.png new file mode 100644 index 0000000000..2fa59b0ada --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c7b387db1b0637745dfc93559b9afa3c637e5a492bf19f6f1d0dbe802ed73bb +size 47156 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_3_en.png new file mode 100644 index 0000000000..8cb2f6776c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9892ec0c06bfa6e0b3a95fd35efa97e44f2e1f6264a324d6fdd994847f1830d1 +size 45897 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_0_en.png new file mode 100644 index 0000000000..a2c2d2043d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91ad7e392e21afe93606956e8e7eab7f0b075574e782ff15e873a71fc3ab16ab +size 15637 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png new file mode 100644 index 0000000000..67cdaf4a39 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d50be9f20ed0e75e337d790edb329996abf9e626591882088817301338fadb6 +size 17213 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_2_en.png new file mode 100644 index 0000000000..6e55a5816e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d76f7b10d8c88f39ab36581be35dd2a5ca5e7c3a92c69b96d4f3ec87f2e93468 +size 46564 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_3_en.png new file mode 100644 index 0000000000..298a35ce39 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:057ceb522ff354d0d7e8b73d59eb53c559f9c22a2727d24744dc6a34b9daaa55 +size 45034 From c9bc7bf28ad3099351b2295df833a9406fcfd64f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Sep 2025 15:12:25 +0200 Subject: [PATCH 018/145] Fix test compilation issues. --- .../matrix/test/spaces/FakeSpaceService.kt | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceService.kt index 54005b122b..43cc8ae8d2 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceService.kt @@ -7,7 +7,9 @@ package io.element.android.libraries.matrix.test.spaces +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import io.element.android.libraries.matrix.api.spaces.SpaceRoomList import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.simulateLongTask @@ -16,17 +18,22 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow class FakeSpaceService( - private val joinedSpacesResult: () -> Result> = { lambdaError() } + private val joinedSpacesResult: () -> Result> = { lambdaError() }, + private val spaceRoomListResult: (RoomId) -> SpaceRoomList = { lambdaError() }, ) : SpaceService { - private val _spaceRooms = MutableSharedFlow>() - override val spaceRooms: SharedFlow> - get() = _spaceRooms.asSharedFlow() + private val _spaceRoomsFlow = MutableSharedFlow>() + override val spaceRoomsFlow: SharedFlow> + get() = _spaceRoomsFlow.asSharedFlow() suspend fun emitSpaceRoomList(value: List) { - _spaceRooms.emit(value) + _spaceRoomsFlow.emit(value) } override suspend fun joinedSpaces(): Result> = simulateLongTask { return joinedSpacesResult() } + + override fun spaceRoomList(id: RoomId): SpaceRoomList { + return spaceRoomListResult(id) + } } From 2128f3c0596eb1b2619ebd93aeea9352b8e95ae9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Sep 2025 15:33:59 +0200 Subject: [PATCH 019/145] Introduce MatrixClient.rememberHideInvitesAvatar() extension to reduce code duplication. --- .../home/impl/roomlist/RoomListPresenter.kt | 9 ++----- .../home/impl/spaces/HomeSpacesPresenter.kt | 9 ++----- .../joinroom/impl/JoinRoomPresenter.kt | 9 ++----- .../features/space/impl/SpacePresenter.kt | 8 ++----- .../libraries/matrix/ui/safety/Avatars.kt | 24 +++++++++++++++++++ 5 files changed, 32 insertions(+), 27 deletions(-) create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/safety/Avatars.kt diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt index 9c77ab816a..b8e299c5e9 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt @@ -36,7 +36,6 @@ import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -44,6 +43,7 @@ import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.libraries.matrix.api.roomlist.RoomList import io.element.android.libraries.matrix.api.timeline.ReceiptType +import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.push.api.battery.BatteryOptimizationState @@ -101,12 +101,7 @@ class RoomListPresenter( var securityBannerDismissed by rememberSaveable { mutableStateOf(false) } // Avatar indicator - val hideInvitesAvatar by remember { - client - .mediaPreviewService() - .mediaPreviewConfigFlow - .mapState { config -> config.hideInviteAvatar } - }.collectAsState() + val hideInvitesAvatar by client.rememberHideInvitesAvatar() val contextMenu = remember { mutableStateOf(RoomListState.ContextMenu.Hidden) } val declineInviteMenu = remember { mutableStateOf(RoomListState.DeclineInviteMenu.Hidden) } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt index b29da29a94..dea6defc0a 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt @@ -14,8 +14,8 @@ import androidx.compose.runtime.remember import dev.zacsweers.metro.Inject import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.toPersistentSet import kotlinx.coroutines.flow.map @@ -27,12 +27,7 @@ class HomeSpacesPresenter( ) : Presenter { @Composable override fun present(): HomeSpacesState { - val hideInvitesAvatar by remember { - client - .mediaPreviewService() - .mediaPreviewConfigFlow - .mapState { config -> config.hideInviteAvatar } - }.collectAsState() + val hideInvitesAvatar by client.rememberHideInvitesAvatar() val spaceRooms by client.spaceService.spaceRoomsFlow.collectAsState(emptyList()) val seenSpaceInvites by remember { seenInvitesStore.seenRoomIds().map { it.toPersistentSet() } 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 04e5b904e6..5fe12a42d9 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 @@ -34,7 +34,6 @@ import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runUpdatingState -import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -50,6 +49,7 @@ import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo import io.element.android.libraries.matrix.ui.model.toInviteSender +import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import java.util.Optional @@ -93,12 +93,7 @@ class JoinRoomPresenter( val forgetRoomAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } var knockMessage by rememberSaveable { mutableStateOf("") } var isDismissingContent by remember { mutableStateOf(false) } - val hideInviteAvatars by remember { - matrixClient - .mediaPreviewService() - .mediaPreviewConfigFlow - .mapState { config -> config.hideInviteAvatar } - }.collectAsState() + val hideInviteAvatars by matrixClient.rememberHideInvitesAvatar() val canReportRoom by produceState(false) { value = matrixClient.canReportRoom() } val contentState by produceState( diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt index d06f1e8eb2..95597371a6 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt @@ -22,6 +22,7 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.spaces.SpaceRoomList +import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentSet @@ -47,12 +48,7 @@ class SpacePresenter( LaunchedEffect(Unit) { paginate() } - val hideInvitesAvatar by remember { - client - .mediaPreviewService() - .mediaPreviewConfigFlow - .mapState { config -> config.hideInviteAvatar } - }.collectAsState() + val hideInvitesAvatar by client.rememberHideInvitesAvatar() val seenSpaceInvites by remember { seenInvitesStore.seenRoomIds().map { it.toPersistentSet() } }.collectAsState(persistentSetOf()) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/safety/Avatars.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/safety/Avatars.kt new file mode 100644 index 0000000000..0eb2b37ea4 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/safety/Avatars.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.ui.safety + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.remember +import io.element.android.libraries.core.coroutine.mapState +import io.element.android.libraries.matrix.api.MatrixClient + +@Composable +fun MatrixClient.rememberHideInvitesAvatar(): State { + return remember { + mediaPreviewService() + .mediaPreviewConfigFlow + .mapState { config -> config.hideInviteAvatar } + }.collectAsState() +} From c982279d5c2cefd9f2a668185ba29cc66323b090 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Sep 2025 16:12:52 +0200 Subject: [PATCH 020/145] Add test on SpacePresenter --- .../features/space/impl/SpacePresenterTest.kt | 167 ++++++++++++++++++ .../matrix/test/spaces/FakeSpaceRoomList.kt | 49 +++++ 2 files changed, 216 insertions(+) create mode 100644 features/space/impl/src/test/kotlin/io/element/android/features/space/impl/SpacePresenterTest.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/SpacePresenterTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/SpacePresenterTest.kt new file mode 100644 index 0000000000..0bcd1303ae --- /dev/null +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/SpacePresenterTest.kt @@ -0,0 +1,167 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package io.element.android.features.space.impl + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.invite.api.SeenInvitesStore +import io.element.android.features.invite.test.InMemorySeenInvitesStore +import io.element.android.features.space.api.SpaceEntryPoint +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.spaces.SpaceRoomList +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.spaces.FakeSpaceRoomList +import io.element.android.libraries.matrix.test.spaces.FakeSpaceService +import io.element.android.libraries.previewutils.room.aSpaceRoom +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class SpacePresenterTest { + @Test + fun `present - initial state`() = runTest { + val paginateResult = lambdaRecorder> { + Result.success(Unit) + } + val presenter = createSpacePresenter( + client = FakeMatrixClient( + spaceService = FakeSpaceService( + spaceRoomListResult = { + FakeSpaceRoomList( + paginateResult = paginateResult, + ) + }, + ), + ), + ) + presenter.test { + val state = awaitItem() + assertThat(state.currentSpace).isNull() + assertThat(state.children).isEmpty() + assertThat(state.seenSpaceInvites).isEmpty() + assertThat(state.hideInvitesAvatar).isFalse() + assertThat(state.hasMoreToLoad).isTrue() + advanceUntilIdle() + paginateResult.assertions().isCalledOnce() + } + } + + @Test + fun `present - load more`() = runTest { + val paginateResult = lambdaRecorder> { + Result.success(Unit) + } + val presenter = createSpacePresenter( + client = FakeMatrixClient( + spaceService = FakeSpaceService( + spaceRoomListResult = { + FakeSpaceRoomList( + paginateResult = paginateResult, + ) + }, + ), + ), + ) + presenter.test { + val state = awaitItem() + advanceUntilIdle() + paginateResult.assertions().isCalledOnce() + state.eventSink(SpaceEvents.LoadMore) + advanceUntilIdle() + paginateResult.assertions().isCalledExactly(2) + } + } + + @Test + fun `present - has more to load value`() = runTest { + val fakeSpaceRoomList = FakeSpaceRoomList( + paginateResult = { Result.success(Unit) }, + ) + val presenter = createSpacePresenter( + client = FakeMatrixClient( + spaceService = FakeSpaceService( + spaceRoomListResult = { fakeSpaceRoomList }, + ), + ), + ) + presenter.test { + val state = awaitItem() + advanceUntilIdle() + assertThat(state.hasMoreToLoad).isTrue() + fakeSpaceRoomList.emitPaginationStatus( + SpaceRoomList.PaginationStatus.Idle(hasMoreToLoad = false) + ) + assertThat(awaitItem().hasMoreToLoad).isFalse() + fakeSpaceRoomList.emitPaginationStatus( + SpaceRoomList.PaginationStatus.Idle(hasMoreToLoad = true) + ) + assertThat(awaitItem().hasMoreToLoad).isTrue() + } + } + + @Test + fun `present - current space value`() = runTest { + val fakeSpaceRoomList = FakeSpaceRoomList( + paginateResult = { Result.success(Unit) }, + ) + val presenter = createSpacePresenter( + client = FakeMatrixClient( + spaceService = FakeSpaceService( + spaceRoomListResult = { fakeSpaceRoomList }, + ), + ), + ) + presenter.test { + val state = awaitItem() + advanceUntilIdle() + assertThat(state.currentSpace).isNull() + val aSpace = aSpaceRoom() + fakeSpaceRoomList.emitCurrentSpace(aSpace) + assertThat(awaitItem().currentSpace).isEqualTo(aSpace) + } + } + + @Test + fun `present - children value`() = runTest { + val fakeSpaceRoomList = FakeSpaceRoomList( + paginateResult = { Result.success(Unit) }, + ) + val presenter = createSpacePresenter( + client = FakeMatrixClient( + spaceService = FakeSpaceService( + spaceRoomListResult = { fakeSpaceRoomList }, + ), + ), + ) + presenter.test { + val state = awaitItem() + advanceUntilIdle() + assertThat(state.children).isEmpty() + val aSpace = aSpaceRoom() + fakeSpaceRoomList.emitSpaceRooms(listOf(aSpace)) + assertThat(awaitItem().children).containsExactly(aSpace) + } + } + + private fun createSpacePresenter( + inputs: SpaceEntryPoint.Inputs = SpaceEntryPoint.Inputs(A_ROOM_ID), + client: MatrixClient = FakeMatrixClient(), + seenInvitesStore: SeenInvitesStore = InMemorySeenInvitesStore(), + ): SpacePresenter { + return SpacePresenter( + inputs = inputs, + client = client, + seenInvitesStore = seenInvitesStore, + ) + } +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt new file mode 100644 index 0000000000..eb71f33fa2 --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.test.spaces + +import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import io.element.android.libraries.matrix.api.spaces.SpaceRoomList +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.StateFlow +import kotlinx.coroutines.flow.asStateFlow + +class FakeSpaceRoomList( + initialSpaceFlowValue: SpaceRoom? = null, + initialSpaceRoomsValue: List = emptyList(), + initialSpaceRoomList: SpaceRoomList.PaginationStatus = SpaceRoomList.PaginationStatus.Loading, + private val paginateResult: () -> Result = { lambdaError() }, +) : SpaceRoomList { + private val _currentSpaceFlow: MutableStateFlow = MutableStateFlow(initialSpaceFlowValue) + override fun currentSpaceFlow(): Flow = _currentSpaceFlow.asStateFlow() + + fun emitCurrentSpace(value: SpaceRoom?) { + _currentSpaceFlow.value = value + } + + private val _spaceRoomsFlow: MutableStateFlow> = MutableStateFlow(initialSpaceRoomsValue) + override val spaceRoomsFlow: Flow> = _spaceRoomsFlow.asStateFlow() + + fun emitSpaceRooms(value: List) { + _spaceRoomsFlow.value = value + } + + private val _paginationStatusFlow: MutableStateFlow = MutableStateFlow(initialSpaceRoomList) + override val paginationStatusFlow: StateFlow = _paginationStatusFlow.asStateFlow() + + fun emitPaginationStatus(value: SpaceRoomList.PaginationStatus) { + _paginationStatusFlow.value = value + } + + override suspend fun paginate(): Result = simulateLongTask { + paginateResult() + } +} From 959cb4f0b3ec66181c136f103ca3678d3a9486c8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Sep 2025 18:18:16 +0200 Subject: [PATCH 021/145] Add test on SpaceRoomCache and fix implementation --- libraries/matrix/impl/build.gradle.kts | 1 + .../matrix/impl/spaces/SpaceRoomCache.kt | 25 +++++----- .../matrix/impl/spaces/SpaceRoomCacheTest.kt | 46 +++++++++++++++++++ 3 files changed, 60 insertions(+), 12 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index a0fa346be2..757d7aa1fc 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -47,6 +47,7 @@ dependencies { testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.preferences.test) + testImplementation(projects.libraries.previewutils) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.toolbox.test) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt index 63fe020ecd..ce039b9471 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt @@ -11,31 +11,32 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.update +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock +import java.util.concurrent.ConcurrentHashMap /** * An in memory cache of space rooms. * Only caches Rooms with roomType [io.element.android.libraries.matrix.api.room.RoomType.Space]. */ class SpaceRoomCache { - private val inMemoryCache = MutableStateFlow>(LinkedHashMap()) + private val inMemoryCache = ConcurrentHashMap>() private val mutex = Mutex() fun getSpaceRoomFlow(roomId: RoomId): Flow { - return inMemoryCache.map { it[roomId] } + return getMutableFlow(roomId).asStateFlow() } suspend fun update(spaceRooms: List) = mutex.withLock { - inMemoryCache.update { cache -> - spaceRooms - .filter { it.isSpace } - .forEach { spaceRoom -> - cache.put(spaceRoom.roomId, spaceRoom) - } - cache - } + spaceRooms + .filter { it.isSpace } + .forEach { spaceRoom -> + getMutableFlow(spaceRoom.roomId).value = spaceRoom + } + } + + private fun getMutableFlow(roomId: RoomId): MutableStateFlow { + return inMemoryCache.getOrPut(roomId, { MutableStateFlow(null) }) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt new file mode 100644 index 0000000000..0679ce1a33 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.spaces + +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.RoomType +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_ID_2 +import io.element.android.libraries.previewutils.room.aSpaceRoom +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class SpaceRoomCacheTest { + @Test + fun `getSpaceRoomFlow emits items`() = runTest { + val sut = SpaceRoomCache() + sut.getSpaceRoomFlow(A_ROOM_ID).test { + assertThat(awaitItem()).isNull() + val room = aSpaceRoom( + roomId = A_ROOM_ID, + roomType = RoomType.Room, + ) + sut.update(listOf(room)) + // Not a space, should not be cached + expectNoEvents() + val space = aSpaceRoom( + roomId = A_ROOM_ID, + roomType = RoomType.Space, + ) + sut.update(listOf(space)) + assertThat(awaitItem()).isEqualTo(space) + val spaceOther = aSpaceRoom( + roomId = A_ROOM_ID_2, + roomType = RoomType.Space, + ) + sut.update(listOf(spaceOther)) + expectNoEvents() + } + } +} From 23cb6146b168de69021a71fc3e577aed04178662 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Sep 2025 17:30:00 +0000 Subject: [PATCH 022/145] Update dependency org.matrix.rustcomponents:sdk-android to v25.9.10 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0825c5049e..aa33901a1d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -176,7 +176,7 @@ jsoup = "org.jsoup:jsoup:1.21.2" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.1.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.1" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.10" 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 697652a5f4dc301621832c94ce1a2e23dec2b875 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 10 Sep 2025 21:42:25 +0200 Subject: [PATCH 023/145] Iterate on SpaceRoomCache thanks to SpaceRoomCacheTest --- .../matrix/impl/spaces/SpaceRoomCache.kt | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt index ce039b9471..8b7d1f5e1b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt @@ -7,36 +7,29 @@ package io.element.android.libraries.matrix.impl.spaces +import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import java.util.concurrent.ConcurrentHashMap +import kotlinx.coroutines.flow.update /** * An in memory cache of space rooms. * Only caches Rooms with roomType [io.element.android.libraries.matrix.api.room.RoomType.Space]. */ class SpaceRoomCache { - private val inMemoryCache = ConcurrentHashMap>() - private val mutex = Mutex() - + private val inMemoryCache = MutableStateFlow>(emptyMap()) fun getSpaceRoomFlow(roomId: RoomId): Flow { - return getMutableFlow(roomId).asStateFlow() + return inMemoryCache.mapState { it[roomId] } } - suspend fun update(spaceRooms: List) = mutex.withLock { - spaceRooms - .filter { it.isSpace } - .forEach { spaceRoom -> - getMutableFlow(spaceRoom.roomId).value = spaceRoom - } - } - - private fun getMutableFlow(roomId: RoomId): MutableStateFlow { - return inMemoryCache.getOrPut(roomId, { MutableStateFlow(null) }) + fun update(spaceRooms: List) { + inMemoryCache.update { currentValues -> + val newValues = spaceRooms + .filter { it.isSpace } + .associateBy { it.roomId } + currentValues + newValues + } } } From 86f3918e78c2d96772da84450a1eeb510c2a1bd7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 07:57:09 +0200 Subject: [PATCH 024/145] Update activity to v1.11.0 (#5324) 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 0825c5049e..01527005cc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ datastore = "1.1.7" constraintlayout = "2.2.1" constraintlayout_compose = "1.1.1" lifecycle = "2.9.2" -activity = "1.10.1" +activity = "1.11.0" media3 = "1.8.0" camera = "1.4.2" From e634952a999a79f024cc745e3b166eecb962829f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Sep 2025 08:52:02 +0200 Subject: [PATCH 025/145] normalizedPowerLevel has been removed from the SDK (and was not used). --- .../impl/messagecomposer/suggestions/SuggestionsPickerView.kt | 1 - .../features/roomdetails/impl/RoomDetailsStateProvider.kt | 2 -- .../roomdetails/impl/members/RoomMemberListStateProvider.kt | 2 -- .../io/element/android/libraries/matrix/api/room/RoomMember.kt | 1 - .../libraries/matrix/impl/room/member/RoomMemberMapper.kt | 1 - .../libraries/matrix/impl/fixtures/factories/RoomMember.kt | 1 - .../android/libraries/matrix/test/room/RoomMemberFixture.kt | 2 -- .../android/libraries/previewutils/room/RoomMemberFixture.kt | 2 -- 8 files changed, 12 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 99a72e06a2..0f0480f404 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 @@ -155,7 +155,6 @@ internal fun SuggestionsPickerViewPreview() { membership = RoomMembershipState.JOIN, isNameAmbiguous = false, powerLevel = 0L, - normalizedPowerLevel = 0L, isIgnored = false, role = RoomMember.Role.User, membershipChangeReason = null, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index e41392ee76..c9087d6458 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -67,7 +67,6 @@ fun aDmRoomMember( membership: RoomMembershipState = RoomMembershipState.JOIN, isNameAmbiguous: Boolean = false, powerLevel: Long = 0, - normalizedPowerLevel: Long = powerLevel, isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, @@ -78,7 +77,6 @@ fun aDmRoomMember( membership = membership, isNameAmbiguous = isNameAmbiguous, powerLevel = powerLevel, - normalizedPowerLevel = normalizedPowerLevel, isIgnored = isIgnored, role = role, membershipChangeReason = membershipChangeReason diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt index 52acb6ebd6..a1cc9c3b92 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt @@ -148,7 +148,6 @@ fun aRoomMember( membership: RoomMembershipState = RoomMembershipState.JOIN, isNameAmbiguous: Boolean = false, powerLevel: Long = 0L, - normalizedPowerLevel: Long = 0L, isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, @@ -159,7 +158,6 @@ fun aRoomMember( membership = membership, isNameAmbiguous = isNameAmbiguous, powerLevel = powerLevel, - normalizedPowerLevel = normalizedPowerLevel, isIgnored = isIgnored, role = role, membershipChangeReason = membershipChangeReason, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt index c2db1e9ec5..f1b1104a27 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt @@ -17,7 +17,6 @@ data class RoomMember( val membership: RoomMembershipState, val isNameAmbiguous: Boolean, val powerLevel: Long, - val normalizedPowerLevel: Long, val isIgnored: Boolean, val role: Role, val membershipChangeReason: String?, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt index 9411ae3aab..af7376e445 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt @@ -25,7 +25,6 @@ object RoomMemberMapper { membership = mapMembership(roomMember.membership), isNameAmbiguous = roomMember.isNameAmbiguous, powerLevel = powerLevel, - normalizedPowerLevel = roomMember.normalizedPowerLevel.into(), isIgnored = roomMember.isIgnored, role = mapRole(roomMember.suggestedRoleForPowerLevel, powerLevel), membershipChangeReason = roomMember.membershipChangeReason diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt index 2922762548..d606008989 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt @@ -30,7 +30,6 @@ fun aRustRoomMember( membership = membership, isNameAmbiguous = isNameAmbiguous, powerLevel = powerLevel, - normalizedPowerLevel = powerLevel, isIgnored = isIgnored, suggestedRoleForPowerLevel = role, membershipChangeReason = membershipChangeReason, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt index e2644cdf4d..9dc72247f0 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt @@ -19,7 +19,6 @@ fun aRoomMember( membership: RoomMembershipState = RoomMembershipState.JOIN, isNameAmbiguous: Boolean = false, powerLevel: Long = 0L, - normalizedPowerLevel: Long = 0L, isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, @@ -30,7 +29,6 @@ fun aRoomMember( membership = membership, isNameAmbiguous = isNameAmbiguous, powerLevel = powerLevel, - normalizedPowerLevel = normalizedPowerLevel, isIgnored = isIgnored, role = role, membershipChangeReason = membershipChangeReason, diff --git a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt index 0c79bb7eeb..e699f3c4b2 100644 --- a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt +++ b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt @@ -19,7 +19,6 @@ fun aRoomMember( membership: RoomMembershipState = RoomMembershipState.JOIN, isNameAmbiguous: Boolean = false, powerLevel: Long = 0L, - normalizedPowerLevel: Long = 0L, isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, @@ -30,7 +29,6 @@ fun aRoomMember( membership = membership, isNameAmbiguous = isNameAmbiguous, powerLevel = powerLevel, - normalizedPowerLevel = normalizedPowerLevel, isIgnored = isIgnored, role = role, membershipChangeReason = membershipChangeReason, From 066bfb13fc3a34b08a9c2f04f2b819ee31e7762b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Sep 2025 08:58:36 +0200 Subject: [PATCH 026/145] SDK API change: handle change on VirtualElementCallWidgetOptions --- .../DefaultCallWidgetSettingsProvider.kt | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt index c45eeaa0ba..1ace9ad4c7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt @@ -21,7 +21,8 @@ import org.matrix.rustcomponents.sdk.newVirtualElementCallWidget import uniffi.matrix_sdk.EncryptionSystem import uniffi.matrix_sdk.HeaderStyle import uniffi.matrix_sdk.NotificationType -import uniffi.matrix_sdk.VirtualElementCallWidgetOptions +import uniffi.matrix_sdk.VirtualElementCallWidgetConfig +import uniffi.matrix_sdk.VirtualElementCallWidgetProperties import uniffi.matrix_sdk.Intent as CallIntent @ContributesBinding(AppScope::class) @@ -33,17 +34,12 @@ class DefaultCallWidgetSettingsProvider( ) : CallWidgetSettingsProvider { override suspend fun provide(baseUrl: String, widgetId: String, encrypted: Boolean, direct: Boolean): MatrixWidgetSettings { val isAnalyticsEnabled = analyticsService.userConsentFlow.first() - val options = VirtualElementCallWidgetOptions( + val properties = VirtualElementCallWidgetProperties( elementCallUrl = baseUrl, widgetId = widgetId, - preload = null, fontScale = null, - appPrompt = false, - confineToRoom = true, font = null, encryption = if (encrypted) EncryptionSystem.PerParticipantKeys else EncryptionSystem.Unencrypted, - intent = CallIntent.START_CALL, - hideScreensharing = false, posthogUserId = callAnalyticsCredentialsProvider.posthogUserId.takeIf { isAnalyticsEnabled }, posthogApiHost = callAnalyticsCredentialsProvider.posthogApiHost.takeIf { isAnalyticsEnabled }, posthogApiKey = callAnalyticsCredentialsProvider.posthogApiKey.takeIf { isAnalyticsEnabled }, @@ -51,13 +47,24 @@ class DefaultCallWidgetSettingsProvider( sentryDsn = callAnalyticsCredentialsProvider.sentryDsn.takeIf { isAnalyticsEnabled }, sentryEnvironment = if (buildMeta.buildType == BuildType.RELEASE) "RELEASE" else "DEBUG", parentUrl = null, + ) + val config = VirtualElementCallWidgetConfig( + preload = null, + appPrompt = false, + confineToRoom = true, + intent = CallIntent.START_CALL, + hideScreensharing = false, // For backwards compatibility, it'll be ignored in recent versions of Element Call hideHeader = true, - controlledMediaDevices = true, + controlledAudioDevices = true, header = HeaderStyle.APP_BAR, sendNotificationType = if (direct) NotificationType.RING else NotificationType.NOTIFICATION, + skipLobby = null, + ) + val rustWidgetSettings = newVirtualElementCallWidget( + props = properties, + config = config, ) - val rustWidgetSettings = newVirtualElementCallWidget(options) return MatrixWidgetSettings.fromRustWidgetSettings(rustWidgetSettings) } } From dcc1545cbf5d7d0c921bef5538a2d257206ba812 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Sep 2025 09:02:43 +0200 Subject: [PATCH 027/145] Add a TODO --- .../matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt index 1ace9ad4c7..f656cc16a4 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt @@ -52,6 +52,7 @@ class DefaultCallWidgetSettingsProvider( preload = null, appPrompt = false, confineToRoom = true, + // TODO We probably want to provide different values for this field. intent = CallIntent.START_CALL, hideScreensharing = false, // For backwards compatibility, it'll be ignored in recent versions of Element Call From 3a301cf4d9a7c63739d19dfd042973dae5ba2594 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 09:04:55 +0200 Subject: [PATCH 028/145] Merge pull request #5322 from element-hq/renovate/com.google.truth-truth-1.x Update dependency com.google.truth:truth to v1.4.5 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 01527005cc..ba3969eff0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -152,7 +152,7 @@ test_runner = "androidx.test:runner:1.7.0" test_mockk = "io.mockk:mockk:1.14.5" test_konsist = "com.lemonappdev:konsist:0.17.3" test_turbine = "app.cash.turbine:turbine:1.2.1" -test_truth = "com.google.truth:truth:1.4.4" +test_truth = "com.google.truth:truth:1.4.5" test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.18" test_robolectric = "org.robolectric:robolectric:4.15.1" test_appyx_junit = { module = "com.bumble.appyx:testing-junit4", version.ref = "appyx" } From 558ecde8ab2245bddd0fb802b0e97474757648d2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 09:54:28 +0200 Subject: [PATCH 029/145] Update dependency io.sentry:sentry-android to v8.21.1 (#5310) 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 ba3969eff0..91d1923e81 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -199,7 +199,7 @@ haze_materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = # Analytics posthog = "com.posthog:posthog-android:3.21.1" -sentry = "io.sentry:sentry-android:8.21.0" +sentry = "io.sentry:sentry-android:8.21.1" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.28.0" From 4869c0b5d799fcb611faf0ec7fbfe9ef2e19178d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Sep 2025 09:36:56 +0200 Subject: [PATCH 030/145] Add UT on SpaceListUpdateProcessor --- .../impl/fixtures/factories/SpaceRoom.kt | 46 +++++ .../spaces/RoomSummaryListProcessorTest.kt | 190 ++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RoomSummaryListProcessorTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt new file mode 100644 index 0000000000..c699ef8097 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures.factories + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.test.A_ROOM_ID +import org.matrix.rustcomponents.sdk.JoinRule +import org.matrix.rustcomponents.sdk.Membership +import org.matrix.rustcomponents.sdk.RoomHero +import org.matrix.rustcomponents.sdk.RoomType +import org.matrix.rustcomponents.sdk.SpaceRoom + +fun aRustSpaceRoom( + roomId: RoomId = A_ROOM_ID, + canonicalAlias: String? = null, + name: String? = null, + topic: String? = null, + avatarUrl: String? = null, + roomType: RoomType = RoomType.Space, + numJoinedMembers: ULong = 0uL, + joinRule: JoinRule? = null, + worldReadable: Boolean? = null, + guestCanJoin: Boolean = false, + childrenCount: ULong = 0uL, + state: Membership? = null, + heroes: List = emptyList(), +) = SpaceRoom( + roomId = roomId.value, + canonicalAlias = canonicalAlias, + name = name, + topic = topic, + avatarUrl = avatarUrl, + roomType = roomType, + numJoinedMembers = numJoinedMembers, + joinRule = joinRule, + worldReadable = worldReadable, + guestCanJoin = guestCanJoin, + childrenCount = childrenCount, + state = state, + heroes = heroes, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RoomSummaryListProcessorTest.kt new file mode 100644 index 0000000000..47c3a19a6b --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RoomSummaryListProcessorTest.kt @@ -0,0 +1,190 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.spaces + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSpaceRoom +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_ID_2 +import io.element.android.libraries.matrix.test.A_ROOM_ID_3 +import io.element.android.libraries.previewutils.room.aSpaceRoom +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.SpaceListUpdate + +class RoomSummaryListProcessorTest { + private val spaceRoomsFlow = MutableStateFlow>(emptyList()) + + @Test + fun `Append adds new entries at the end of the list`() = runTest { + spaceRoomsFlow.value = listOf(aSpaceRoom()) + val processor = createProcessor() + + val newEntry = aRustSpaceRoom(roomId = A_ROOM_ID_2) + processor.postUpdates(listOf(SpaceListUpdate.Append(listOf(newEntry, newEntry, newEntry)))) + + assertThat(spaceRoomsFlow.value.count()).isEqualTo(4) + assertThat(spaceRoomsFlow.value.subList(1, 4).all { it.roomId == A_ROOM_ID_2 }).isTrue() + } + + @Test + fun `PushBack adds a new entry at the end of the list`() = runTest { + spaceRoomsFlow.value = listOf(aSpaceRoom()) + val processor = createProcessor() + processor.postUpdates(listOf(SpaceListUpdate.PushBack(aRustSpaceRoom(roomId = A_ROOM_ID_2)))) + + assertThat(spaceRoomsFlow.value.count()).isEqualTo(2) + assertThat(spaceRoomsFlow.value.last().roomId).isEqualTo(A_ROOM_ID_2) + } + + @Test + fun `PushFront inserts a new entry at the start of the list`() = runTest { + spaceRoomsFlow.value = listOf(aSpaceRoom()) + val processor = createProcessor() + processor.postUpdates(listOf(SpaceListUpdate.PushFront(aRustSpaceRoom(roomId = A_ROOM_ID_2)))) + + assertThat(spaceRoomsFlow.value.count()).isEqualTo(2) + assertThat(spaceRoomsFlow.value.first().roomId).isEqualTo(A_ROOM_ID_2) + } + + @Test + fun `Set replaces an entry at some index`() = runTest { + spaceRoomsFlow.value = listOf(aSpaceRoom()) + val processor = createProcessor() + val index = 0 + + processor.postUpdates(listOf(SpaceListUpdate.Set(index.toUInt(), aRustSpaceRoom(roomId = A_ROOM_ID_2)))) + + assertThat(spaceRoomsFlow.value.count()).isEqualTo(1) + assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2) + } + + @Test + fun `Insert inserts a new entry at the provided index`() = runTest { + spaceRoomsFlow.value = listOf(aSpaceRoom()) + val processor = createProcessor() + val index = 0 + + processor.postUpdates(listOf(SpaceListUpdate.Insert(index.toUInt(), aRustSpaceRoom(roomId = A_ROOM_ID_2)))) + + assertThat(spaceRoomsFlow.value.count()).isEqualTo(2) + assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2) + } + + @Test + fun `Remove removes an entry at some index`() = runTest { + spaceRoomsFlow.value = listOf( + aSpaceRoom(roomId = A_ROOM_ID), + aSpaceRoom(roomId = A_ROOM_ID_2) + ) + val processor = createProcessor() + val index = 0 + + processor.postUpdates(listOf(SpaceListUpdate.Remove(index.toUInt()))) + + assertThat(spaceRoomsFlow.value.count()).isEqualTo(1) + assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2) + } + + @Test + fun `PopBack removes an entry at the end of the list`() = runTest { + spaceRoomsFlow.value = listOf( + aSpaceRoom(roomId = A_ROOM_ID), + aSpaceRoom(roomId = A_ROOM_ID_2) + ) + val processor = createProcessor() + val index = 0 + + processor.postUpdates(listOf(SpaceListUpdate.PopBack)) + + assertThat(spaceRoomsFlow.value.count()).isEqualTo(1) + assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID) + } + + @Test + fun `PopFront removes an entry at the start of the list`() = runTest { + spaceRoomsFlow.value = listOf( + aSpaceRoom(roomId = A_ROOM_ID), + aSpaceRoom(roomId = A_ROOM_ID_2) + ) + val processor = createProcessor() + val index = 0 + + processor.postUpdates(listOf(SpaceListUpdate.PopFront)) + + assertThat(spaceRoomsFlow.value.count()).isEqualTo(1) + assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2) + } + + @Test + fun `Clear removes all the entries`() = runTest { + spaceRoomsFlow.value = listOf( + aSpaceRoom(roomId = A_ROOM_ID), + aSpaceRoom(roomId = A_ROOM_ID_2) + ) + val processor = createProcessor() + + processor.postUpdates(listOf(SpaceListUpdate.Clear)) + + assertThat(spaceRoomsFlow.value).isEmpty() + } + + @Test + fun `Truncate removes all entries after the provided length`() = runTest { + spaceRoomsFlow.value = listOf( + aSpaceRoom(roomId = A_ROOM_ID), + aSpaceRoom(roomId = A_ROOM_ID_2) + ) + val processor = createProcessor() + val index = 0 + + processor.postUpdates(listOf(SpaceListUpdate.Truncate(1u))) + + assertThat(spaceRoomsFlow.value.count()).isEqualTo(1) + assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID) + } + + @Test + fun `Reset removes all entries and add the provided ones`() = runTest { + spaceRoomsFlow.value = listOf( + aSpaceRoom(roomId = A_ROOM_ID), + aSpaceRoom(roomId = A_ROOM_ID_2) + ) + val processor = createProcessor() + val index = 0 + + processor.postUpdates(listOf(SpaceListUpdate.Reset(listOf(aRustSpaceRoom(A_ROOM_ID_3))))) + + assertThat(spaceRoomsFlow.value.count()).isEqualTo(1) + assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_3) + } + + @Test + fun `When there is no replay cache SpaceListUpdateProcessor starts with an empty list`() = runTest { + val spaceRoomsSharedFlow = MutableSharedFlow>(replay = 1) + val processor = createProcessor( + spaceRoomsFlow = spaceRoomsSharedFlow, + ) + assertThat(spaceRoomsSharedFlow.replayCache).isEmpty() + val newEntry = aRustSpaceRoom(roomId = A_ROOM_ID) + processor.postUpdates(listOf(SpaceListUpdate.Append(listOf(newEntry)))) + assertThat(spaceRoomsSharedFlow.replayCache).hasSize(1) + assertThat(spaceRoomsSharedFlow.replayCache.first()).hasSize(1) + } + + private fun createProcessor( + spaceRoomsFlow: MutableSharedFlow> = this.spaceRoomsFlow, + ) = SpaceListUpdateProcessor( + spaceRoomsFlow = spaceRoomsFlow, + mapper = SpaceRoomMapper(), + spaceRoomCache = SpaceRoomCache(), + ) +} From ba372c018b80ecb3369a1fbfd457485caa383508 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Sep 2025 10:15:23 +0200 Subject: [PATCH 031/145] Fix quality issue. --- .../libraries/matrix/test/spaces/FakeSpaceRoomList.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt index eb71f33fa2..cd5bf7eb53 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt @@ -22,11 +22,11 @@ class FakeSpaceRoomList( initialSpaceRoomList: SpaceRoomList.PaginationStatus = SpaceRoomList.PaginationStatus.Loading, private val paginateResult: () -> Result = { lambdaError() }, ) : SpaceRoomList { - private val _currentSpaceFlow: MutableStateFlow = MutableStateFlow(initialSpaceFlowValue) - override fun currentSpaceFlow(): Flow = _currentSpaceFlow.asStateFlow() + private val currentSpaceMutableStateFlow: MutableStateFlow = MutableStateFlow(initialSpaceFlowValue) + override fun currentSpaceFlow(): Flow = currentSpaceMutableStateFlow.asStateFlow() fun emitCurrentSpace(value: SpaceRoom?) { - _currentSpaceFlow.value = value + currentSpaceMutableStateFlow.value = value } private val _spaceRoomsFlow: MutableStateFlow> = MutableStateFlow(initialSpaceRoomsValue) From e20b3550dc673ccd512dc900065dadd6191cbe88 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 9 Sep 2025 09:59:40 +0200 Subject: [PATCH 032/145] Call: RTC decline event support --- .../call/impl/utils/ActiveCallManager.kt | 45 ++++++++ .../utils/DefaultActiveCallManagerTest.kt | 106 ++++++++++++++++++ .../libraries/matrix/api/room/BaseRoom.kt | 7 +- .../matrix/impl/room/RustBaseRoom.kt | 18 +++ .../matrix/test/room/FakeBaseRoom.kt | 17 +++ 5 files changed, 192 insertions(+), 1 deletion(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index 54a5e567c8..45d6ffedb2 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -186,6 +186,15 @@ class DefaultActiveCallManager( } Timber.tag(tag).d("Hung up call: $callType") + if (activeCall.value?.callState is CallState.Ringing) { + val ringing = activeCall.value!!.callState as CallState.Ringing + // Decline the call + matrixClientProvider.getOrRestore(ringing.notificationData.sessionId).getOrNull()?.let { client -> + client.getRoom(ringing.notificationData.roomId)?.let { room -> + room.declineCall(ringing.notificationData.eventId) + } + } + } cancelIncomingCallNotification() if (activeWakeLock?.isHeld == true) { @@ -256,6 +265,42 @@ class DefaultActiveCallManager( @OptIn(ExperimentalCoroutinesApi::class) private fun observeRingingCall() { + activeCall + .filterNotNull() + .filter { it.callState is CallState.Ringing && it.callType is CallType.RoomCall } + .flatMapLatest { activeCall -> + val callType = activeCall.callType as CallType.RoomCall + val ringingInfo = activeCall.callState as CallState.Ringing + val client = matrixClientProvider.getOrRestore(callType.sessionId).getOrNull() ?: run { + Timber.tag(tag).d("Couldn't find room for incoming call: $activeCall") + return@flatMapLatest flowOf() + } + val room = client.getRoom(callType.roomId) ?: run { + Timber.tag(tag).d("Couldn't find room for incoming call: $activeCall") + return@flatMapLatest flowOf() + } + + Timber.tag(tag).d("Found room for rining call: ${room.roomId}") + + // If we have declined from another phone we want to stop ringing. + room.subscribeToCallDecline(ringingInfo.notificationData.eventId) + .filter { decliner -> + Timber.tag(tag).d("Call: $activeCall was declined by $decliner") + // only want to listen if the call was declined from another of my sessions, + // (we are ringing for an incoming call in a DM) + decliner == client.sessionId + } + }.onEach { decliner -> + Timber.tag(tag).d("Call: $activeCall was declined by from another session") + // decline + activeCall.value = null + if (activeWakeLock?.isHeld == true) { + Timber.tag(tag).d("Releasing partial wakelock after timeout") + activeWakeLock.release() + } + cancelIncomingCallNotification() + } + .launchIn(coroutineScope) // This will observe ringing calls and ensure they're terminated if the room call is cancelled or if the user // has joined the call from another session. activeCall diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt index 84084c38fe..2b2e4738fa 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt @@ -22,13 +22,16 @@ import io.element.android.features.call.test.aCallNotificationData import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.room.JoinedRoom 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.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID_2 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.FakeBaseRoom +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.push.api.notifications.ForegroundServiceType import io.element.android.libraries.push.api.notifications.NotificationIdProvider @@ -38,6 +41,7 @@ import io.element.android.libraries.push.test.notifications.push.FakeNotificatio import io.element.android.services.appnavstate.test.FakeAppForegroundStateService import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value +import io.mockk.coVerify import io.mockk.mockk import io.mockk.verify import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -49,6 +53,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.Shadows.shadowOf +import timber.log.Timber @RunWith(RobolectricTestRunner::class) class DefaultActiveCallManagerTest { @@ -164,6 +169,107 @@ class DefaultActiveCallManagerTest { verify { notificationManagerCompat.cancel(notificationId) } } + @Test + fun `Decline event - Hangup on a ringing call should send a decline event`() = runTest { + setupShadowPowerManager() + val notificationManagerCompat = mockk(relaxed = true) + + val room = mockk(relaxed = true) + + val matrixClient = FakeMatrixClient().apply { + givenGetRoomResult(A_ROOM_ID, room) + } + val clientProvider = FakeMatrixClientProvider({ Result.success(matrixClient) }) + + val manager = createActiveCallManager( + matrixClientProvider = clientProvider, + notificationManagerCompat = notificationManagerCompat + ) + + val notificationData = aCallNotificationData(roomId = A_ROOM_ID) + manager.registerIncomingCall(notificationData) + + manager.hungUpCall(CallType.RoomCall(notificationData.sessionId, notificationData.roomId)) + + coVerify { + room.declineCall(notificationEventId = notificationData.eventId) + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `Decline event - Declining from another session should stop ringing`() = runTest { + setupShadowPowerManager() + val notificationManagerCompat = mockk(relaxed = true) + + val room = FakeJoinedRoom() + + val matrixClient = FakeMatrixClient().apply { + givenGetRoomResult(A_ROOM_ID, room) + } + val clientProvider = FakeMatrixClientProvider({ Result.success(matrixClient) }) + + val manager = createActiveCallManager( + matrixClientProvider = clientProvider, + notificationManagerCompat = notificationManagerCompat + ) + + val notificationData = aCallNotificationData(roomId = A_ROOM_ID) + manager.registerIncomingCall(notificationData) + + runCurrent() + + // Simulate declined from other session + room.baseRoom.givenDecliner(matrixClient.sessionId, notificationData.eventId) + + runCurrent() + + assertThat(manager.activeCall.value).isNull() + assertThat(manager.activeWakeLock?.isHeld).isFalse() + + verify { notificationManagerCompat.cancel(notificationId) } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `Decline event - Should ignore decline for other notification events`() = runTest { + Timber.plant(object : Timber.Tree() { + override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { + println("$tag: $message") + } + }) + + setupShadowPowerManager() + val notificationManagerCompat = mockk(relaxed = true) + + val room = FakeJoinedRoom() + + val matrixClient = FakeMatrixClient().apply { + givenGetRoomResult(A_ROOM_ID, room) + } + val clientProvider = FakeMatrixClientProvider({ Result.success(matrixClient) }) + + val manager = createActiveCallManager( + matrixClientProvider = clientProvider, + notificationManagerCompat = notificationManagerCompat + ) + + val notificationData = aCallNotificationData(roomId = A_ROOM_ID) + manager.registerIncomingCall(notificationData) + + runCurrent() + + // Simulate declined for another notification event + room.baseRoom.givenDecliner(matrixClient.sessionId, AN_EVENT_ID_2) + + runCurrent() + + assertThat(manager.activeCall.value).isNotNull() + assertThat(manager.activeWakeLock?.isHeld).isTrue() + + verify(exactly = 0) { notificationManagerCompat.cancel(notificationId) } + } + @Test fun `hungUpCall - does nothing if the CallType doesn't match`() = runTest { setupShadowPowerManager() diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt index 7e902a66fa..84aae82b66 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt @@ -18,6 +18,7 @@ import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.api.timeline.ReceiptType import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import java.io.Closeable @@ -239,7 +240,11 @@ interface BaseRoom : Closeable { */ suspend fun reportRoom(reason: String?): Result - /** + suspend fun declineCall(notificationEventId: EventId): Result + + suspend fun subscribeToCallDecline(notificationEventId: EventId): Flow + + /** * Destroy the room and release all resources associated to it. */ fun destroy() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt index 975185242b..37926a59ee 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt @@ -38,10 +38,12 @@ import io.element.android.libraries.matrix.impl.timeline.toRustReceiptType import io.element.android.libraries.matrix.impl.util.mxCallbackFlow import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext +import org.matrix.rustcomponents.sdk.CallDeclineListener import org.matrix.rustcomponents.sdk.RoomInfoListener import org.matrix.rustcomponents.sdk.use import timber.log.Timber @@ -300,4 +302,20 @@ class RustBaseRoom( innerRoom.reportRoom(reason.orEmpty()) } } + + override suspend fun declineCall(notificationEventId: EventId): Result = withContext(roomDispatcher) { + runCatchingExceptions { + innerRoom.declineCall(notificationEventId.toString()) + } + } + + override suspend fun subscribeToCallDecline(notificationEventId: EventId): Flow = withContext(roomDispatcher) { + mxCallbackFlow { + innerRoom.subscribeToCallDeclineEvents(notificationEventId.toString(), object : CallDeclineListener { + override fun call(declinerUserId: String) { + trySend(UserId(declinerUserId)) + } + }) + } + } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt index 2a61c48e50..3ec9c3f870 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt @@ -29,6 +29,8 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.simulateLongTask import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.test.TestScope @@ -77,6 +79,12 @@ class FakeBaseRoom( _roomInfoFlow.tryEmit(roomInfo) } + private val declineCallFlowMap: MutableMap> = mutableMapOf() + + suspend fun givenDecliner(userId: UserId, forNotificationEventId: EventId) { + declineCallFlowMap[forNotificationEventId]?.emit(userId) + } + override val membersStateFlow: MutableStateFlow = MutableStateFlow(RoomMembersState.Unknown) override suspend fun updateMembers() = updateMembersResult() @@ -222,6 +230,15 @@ class FakeBaseRoom( override suspend fun reportRoom(reason: String?) = reportRoomResult(reason) + override suspend fun declineCall(notificationEventId: EventId): Result { + return Result.success(Unit) + } + + override suspend fun subscribeToCallDecline(notificationEventId: EventId): Flow { + val flow = declineCallFlowMap.getOrPut(notificationEventId, { MutableSharedFlow() }) + return flow + } + override fun predecessorRoom(): PredecessorRoom? = predecessorRoomResult() fun givenUpdateMembersResult(result: () -> Unit) { From 9546a731d4112b39a949e1749506923dd7862f47 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 11 Sep 2025 13:41:24 +0200 Subject: [PATCH 033/145] fix detekt --- .../android/features/call/impl/utils/ActiveCallManager.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/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index 45d6ffedb2..a3591ff945 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -290,7 +290,8 @@ class DefaultActiveCallManager( // (we are ringing for an incoming call in a DM) decliner == client.sessionId } - }.onEach { decliner -> + } + .onEach { decliner -> Timber.tag(tag).d("Call: $activeCall was declined by from another session") // decline activeCall.value = null From 3b41d4a7e809bfbceefcbd416ae111266d49d308 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Sep 2025 14:51:56 +0200 Subject: [PATCH 034/145] Add tests on RustSpaceRoomList --- .../fixtures/fakes/FakeFfiSpaceRoomList.kt | 58 +++++++++ .../impl/spaces/RustSpaceRoomListTest.kt | 118 ++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt new file mode 100644 index 0000000000..171afd49fc --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures.fakes + +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.simulateLongTask +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.SpaceListUpdate +import org.matrix.rustcomponents.sdk.SpaceRoom +import org.matrix.rustcomponents.sdk.SpaceRoomList +import org.matrix.rustcomponents.sdk.SpaceRoomListEntriesListener +import org.matrix.rustcomponents.sdk.SpaceRoomListPaginationStateListener +import org.matrix.rustcomponents.sdk.TaskHandle +import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState + +class FakeFfiSpaceRoomList( + private val paginateResult: () -> Unit = { lambdaError() }, + private val paginationStateResult: () -> SpaceRoomListPaginationState = { lambdaError() }, + private val roomsResult: () -> List = { lambdaError() }, +) : SpaceRoomList(NoPointer) { + private var spaceRoomListPaginationStateListener: SpaceRoomListPaginationStateListener? = null + private var spaceRoomListEntriesListener: SpaceRoomListEntriesListener? = null + + override suspend fun paginate() = simulateLongTask { + paginateResult() + } + + override fun paginationState(): SpaceRoomListPaginationState { + return paginationStateResult() + } + + override fun rooms(): List { + return roomsResult() + } + + override fun subscribeToPaginationStateUpdates(listener: SpaceRoomListPaginationStateListener): TaskHandle { + spaceRoomListPaginationStateListener = listener + return FakeFfiTaskHandle() + } + + fun triggerPaginationStateUpdate(state: SpaceRoomListPaginationState) { + spaceRoomListPaginationStateListener?.onUpdate(state) + } + + override fun subscribeToRoomUpdate(listener: SpaceRoomListEntriesListener): TaskHandle { + spaceRoomListEntriesListener = listener + return FakeFfiTaskHandle() + } + + fun triggerRoomListUpdate(rooms: List) { + spaceRoomListEntriesListener?.onUpdate(rooms) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt new file mode 100644 index 0000000000..6ef3259657 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt @@ -0,0 +1,118 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package io.element.android.libraries.matrix.impl.spaces + +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.spaces.SpaceRoomList +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSpaceRoom +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiSpaceRoomList +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_ID_2 +import io.element.android.libraries.previewutils.room.aSpaceRoom +import io.element.android.tests.testutils.lambda.lambdaRecorder +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.SpaceListUpdate +import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState +import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList + +class RustSpaceRoomListTest { + @Test + fun `paginationStatusFlow emits values`() = runTest { + val innerSpaceRoomList = FakeFfiSpaceRoomList( + paginationStateResult = { SpaceRoomListPaginationState.Idle(false) } + ) + val sut = createRustSpaceRoomList( + innerSpaceRoomList = innerSpaceRoomList, + ) + sut.paginationStatusFlow.test { + // First value is the initial one + assertThat(awaitItem()).isEqualTo(SpaceRoomList.PaginationStatus.Idle(hasMoreToLoad = false)) + // First value after the subscription occurs + assertThat(awaitItem()).isEqualTo(SpaceRoomList.PaginationStatus.Idle(hasMoreToLoad = true)) + innerSpaceRoomList.triggerPaginationStateUpdate(SpaceRoomListPaginationState.Loading) + assertThat(awaitItem()).isEqualTo(SpaceRoomList.PaginationStatus.Loading) + innerSpaceRoomList.triggerPaginationStateUpdate(SpaceRoomListPaginationState.Idle(true)) + assertThat(awaitItem()).isEqualTo(SpaceRoomList.PaginationStatus.Idle(hasMoreToLoad = false)) + innerSpaceRoomList.triggerPaginationStateUpdate(SpaceRoomListPaginationState.Idle(false)) + assertThat(awaitItem()).isEqualTo(SpaceRoomList.PaginationStatus.Idle(hasMoreToLoad = true)) + } + } + + @Test + fun `spaceRoomsFlow emits values`() = runTest { + val innerSpaceRoomList = FakeFfiSpaceRoomList( + paginationStateResult = { SpaceRoomListPaginationState.Idle(false) } + ) + val sut = createRustSpaceRoomList( + innerSpaceRoomList = innerSpaceRoomList, + ) + sut.spaceRoomsFlow.test { + // Give time for the subscription to be set + runCurrent() + innerSpaceRoomList.triggerRoomListUpdate( + listOf( + SpaceListUpdate.PushBack(aRustSpaceRoom(roomId = A_ROOM_ID_2)) + ) + ) + val rooms = awaitItem() + assertThat(rooms).hasSize(1) + assertThat(rooms[0].roomId).isEqualTo(A_ROOM_ID_2) + } + } + + @Test + fun `paginate invokes paginate on the inner class`() = runTest { + val paginateResult = lambdaRecorder { } + val innerSpaceRoomList = FakeFfiSpaceRoomList( + paginateResult = paginateResult, + ) + val sut = createRustSpaceRoomList( + innerSpaceRoomList = innerSpaceRoomList, + ) + sut.paginate() + paginateResult.assertions().isCalledOnce() + } + + @Test + fun `currentSpaceFlow reads value from the SpaceRoomCache`() = runTest { + val spaceRoomCache = SpaceRoomCache() + val sut = createRustSpaceRoomList( + spaceRoomCache = spaceRoomCache, + ) + sut.currentSpaceFlow().test { + assertThat(awaitItem()).isNull() + val spaceRoom = aSpaceRoom(roomId = A_ROOM_ID) + spaceRoomCache.update(listOf(spaceRoom)) + assertThat(awaitItem()).isEqualTo(spaceRoom) + } + } + + private fun TestScope.createRustSpaceRoomList( + roomId: RoomId = A_ROOM_ID, + innerSpaceRoomList: InnerSpaceRoomList = FakeFfiSpaceRoomList(), + innerProvider: suspend () -> InnerSpaceRoomList = { innerSpaceRoomList }, + spaceRoomMapper: SpaceRoomMapper = SpaceRoomMapper(), + spaceRoomCache: SpaceRoomCache = SpaceRoomCache(), + ): RustSpaceRoomList { + return RustSpaceRoomList( + roomId = roomId, + innerProvider = innerProvider, + sessionCoroutineScope = backgroundScope, + spaceRoomMapper = spaceRoomMapper, + spaceRoomCache = spaceRoomCache, + ) + } +} From 9585f597255e8581775931ecfea686b95ed31b7e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Sep 2025 16:21:32 +0200 Subject: [PATCH 035/145] Code cleanup. Avoid usage of !! --- .../call/impl/utils/ActiveCallManager.kt | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index a3591ff945..6ec35009f9 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -180,20 +180,21 @@ class DefaultActiveCallManager( } override suspend fun hungUpCall(callType: CallType) = mutex.withLock { - if (activeCall.value?.callType != callType) { + Timber.tag(tag).d("Hung up call: $callType") + val currentActiveCall = activeCall.value ?: run { + Timber.tag(tag).w("No active call, ignoring hang up") + return + } + if (currentActiveCall.callType != callType) { Timber.tag(tag).w("Call type $callType does not match the active call type, ignoring") return } - - Timber.tag(tag).d("Hung up call: $callType") - if (activeCall.value?.callState is CallState.Ringing) { - val ringing = activeCall.value!!.callState as CallState.Ringing + if (currentActiveCall.callState is CallState.Ringing) { // Decline the call - matrixClientProvider.getOrRestore(ringing.notificationData.sessionId).getOrNull()?.let { client -> - client.getRoom(ringing.notificationData.roomId)?.let { room -> - room.declineCall(ringing.notificationData.eventId) - } - } + val notificationData = currentActiveCall.callState.notificationData + matrixClientProvider.getOrRestore(notificationData.sessionId).getOrNull() + ?.getRoom(notificationData.roomId) + ?.declineCall(notificationData.eventId) } cancelIncomingCallNotification() From 95207ee6eb2995e211f6d56d20e8cb99c0043a7d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Sep 2025 16:37:12 +0200 Subject: [PATCH 036/145] Improve log messages and comment --- .../features/call/impl/utils/ActiveCallManager.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index 6ec35009f9..0895e6860b 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -273,7 +273,7 @@ class DefaultActiveCallManager( val callType = activeCall.callType as CallType.RoomCall val ringingInfo = activeCall.callState as CallState.Ringing val client = matrixClientProvider.getOrRestore(callType.sessionId).getOrNull() ?: run { - Timber.tag(tag).d("Couldn't find room for incoming call: $activeCall") + Timber.tag(tag).d("Couldn't find session for incoming call: $activeCall") return@flatMapLatest flowOf() } val room = client.getRoom(callType.roomId) ?: run { @@ -281,7 +281,7 @@ class DefaultActiveCallManager( return@flatMapLatest flowOf() } - Timber.tag(tag).d("Found room for rining call: ${room.roomId}") + Timber.tag(tag).d("Found room for ringing call: ${room.roomId}") // If we have declined from another phone we want to stop ringing. room.subscribeToCallDecline(ringingInfo.notificationData.eventId) @@ -293,11 +293,11 @@ class DefaultActiveCallManager( } } .onEach { decliner -> - Timber.tag(tag).d("Call: $activeCall was declined by from another session") - // decline + Timber.tag(tag).d("Call: $activeCall was declined by user from another session") + // Remove the active call and cancel the notification activeCall.value = null if (activeWakeLock?.isHeld == true) { - Timber.tag(tag).d("Releasing partial wakelock after timeout") + Timber.tag(tag).d("Releasing partial wakelock after call declined from another session") activeWakeLock.release() } cancelIncomingCallNotification() From baf922e9ba5f2eaac8cf8acc1468f65ba265f4a9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 16:44:20 +0200 Subject: [PATCH 037/145] Update dependency androidx.sqlite:sqlite-ktx to v2.6.0 (#5337) 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 c8d3376ba8..f7d96ede36 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -183,7 +183,7 @@ sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", ver sqldelight-driver-jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" } sqlcipher = "net.zetetic:sqlcipher-android:4.10.0" -sqlite = "androidx.sqlite:sqlite-ktx:2.5.2" +sqlite = "androidx.sqlite:sqlite-ktx:2.6.0" unifiedpush = "org.unifiedpush.android:connector:3.0.10" vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil", version.ref = "telephoto" } From 0b5cb57e469130097f40e9109e676e3931ddd827 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Sep 2025 16:58:47 +0200 Subject: [PATCH 038/145] Extract plantTestTimber --- .../call/utils/DefaultActiveCallManagerTest.kt | 9 ++------- .../element/android/tests/testutils/Timber.kt | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 tests/testutils/src/main/kotlin/io/element/android/tests/testutils/Timber.kt diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt index 2b2e4738fa..d842126c67 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt @@ -41,6 +41,7 @@ import io.element.android.libraries.push.test.notifications.push.FakeNotificatio import io.element.android.services.appnavstate.test.FakeAppForegroundStateService import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value +import io.element.android.tests.testutils.plantTestTimber import io.mockk.coVerify import io.mockk.mockk import io.mockk.verify @@ -53,7 +54,6 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.Shadows.shadowOf -import timber.log.Timber @RunWith(RobolectricTestRunner::class) class DefaultActiveCallManagerTest { @@ -233,12 +233,7 @@ class DefaultActiveCallManagerTest { @OptIn(ExperimentalCoroutinesApi::class) @Test fun `Decline event - Should ignore decline for other notification events`() = runTest { - Timber.plant(object : Timber.Tree() { - override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { - println("$tag: $message") - } - }) - + plantTestTimber() setupShadowPowerManager() val notificationManagerCompat = mockk(relaxed = true) diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/Timber.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/Timber.kt new file mode 100644 index 0000000000..2aad499698 --- /dev/null +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/Timber.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.tests.testutils + +import timber.log.Timber + +fun plantTestTimber() { + Timber.plant(object : Timber.Tree() { + override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { + println("$tag: $message") + } + }) +} From 5bbe299627f58d42048717d784423c325f8acd0a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Sep 2025 17:04:58 +0200 Subject: [PATCH 039/145] Use `.value` instead of `.toString()`. --- .../roommembermoderation/impl/RoomMemberModerationView.kt | 2 +- .../impl/DefaultBaseRoomLastMessageFormatterTest.kt | 2 +- .../android/libraries/matrix/api/core/MatrixPatterns.kt | 2 +- .../android/libraries/matrix/impl/room/RustBaseRoom.kt | 4 ++-- .../android/libraries/matrix/impl/room/join/AllowRule.kt | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt index d4b7a7b69e..248b6cd02b 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt @@ -242,7 +242,7 @@ private fun RoomMemberActionsBottomSheet( ) } Text( - text = user.userId.toString(), + text = user.userId.value, style = ElementTheme.typography.fontBodyLgRegular, color = ElementTheme.colors.textSecondary, maxLines = 1, diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt index ee56fcf2c5..0a7d2c1e73 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt @@ -102,7 +102,7 @@ class DefaultBaseRoomLastMessageFormatterTest { val info = ImageInfo(null, null, null, null, null, null, null) val message = createRoomEvent(false, null, aStickerContent(body, info, aMediaSource(url = "url"))) val result = formatter.format(message, false) - val expectedBody = someoneElseId.toString() + ": Sticker (a sticker body)" + val expectedBody = someoneElseId.value + ": Sticker (a sticker body)" assertThat(result.toString()).isEqualTo(expectedBody) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt index a44e00b664..26a030d361 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt @@ -151,7 +151,7 @@ object MatrixPatterns { val urlMatch = match.groupValues[1] when (val permalink = permalinkParser.parse(urlMatch)) { is PermalinkData.UserLink -> { - add(MatrixPatternResult(MatrixPatternType.USER_ID, permalink.userId.toString(), match.range.first, match.range.last + 1)) + add(MatrixPatternResult(MatrixPatternType.USER_ID, permalink.userId.value, match.range.first, match.range.last + 1)) } is PermalinkData.RoomLink -> { when (permalink.roomIdOrAlias) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt index 37926a59ee..1ca5915c71 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt @@ -305,13 +305,13 @@ class RustBaseRoom( override suspend fun declineCall(notificationEventId: EventId): Result = withContext(roomDispatcher) { runCatchingExceptions { - innerRoom.declineCall(notificationEventId.toString()) + innerRoom.declineCall(notificationEventId.value) } } override suspend fun subscribeToCallDecline(notificationEventId: EventId): Flow = withContext(roomDispatcher) { mxCallbackFlow { - innerRoom.subscribeToCallDeclineEvents(notificationEventId.toString(), object : CallDeclineListener { + innerRoom.subscribeToCallDeclineEvents(notificationEventId.value, object : CallDeclineListener { override fun call(declinerUserId: String) { trySend(UserId(declinerUserId)) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/join/AllowRule.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/join/AllowRule.kt index ae74e1edc0..a93ce58236 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/join/AllowRule.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/join/AllowRule.kt @@ -20,7 +20,7 @@ fun RustAllowRule.map(): AllowRule { fun AllowRule.map(): RustAllowRule { return when (this) { - is AllowRule.RoomMembership -> RustAllowRule.RoomMembership(roomId.toString()) + is AllowRule.RoomMembership -> RustAllowRule.RoomMembership(roomId.value) is AllowRule.Custom -> RustAllowRule.Custom(json) } } From f879c2e1e1388dd6e0e7be324743e9bbc546bd92 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 17:13:27 +0200 Subject: [PATCH 040/145] Update camera to v1.5.0 (#5336) 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 f7d96ede36..151afbf2d7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ constraintlayout_compose = "1.1.1" lifecycle = "2.9.2" activity = "1.11.0" media3 = "1.8.0" -camera = "1.4.2" +camera = "1.5.0" # Compose compose_bom = "2025.07.00" From 0ebabe31a993e77df2d0835fbd392a488ba89eb2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 17:13:49 +0200 Subject: [PATCH 041/145] Update dependency com.posthog:posthog-android to v3.21.2 (#5333) 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 151afbf2d7..8b79d99011 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -198,7 +198,7 @@ haze = { module = "dev.chrisbanes.haze:haze", version.ref = "haze" } haze_materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = "haze" } # Analytics -posthog = "com.posthog:posthog-android:3.21.1" +posthog = "com.posthog:posthog-android:3.21.2" sentry = "io.sentry:sentry-android:8.21.1" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.28.0" From 120c30e076447bb436dd8521424148ce96b6561d Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Fri, 12 Sep 2025 11:35:37 +0100 Subject: [PATCH 042/145] Show progress dialog while we are sending invites in a room (#5342) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add `InvitePeopleState.sendInvitesAction` Keep track of the progress on sending invites with a new state property. * Keep `RoomInviteMembersView` open until invites are sent * Sync strings from localazy * extend `ProgressDialog` to support custom content For my current design, a simple text element is insufficient. I extend `ProgressDialog` to give more flexibility over the content of the dialog. * Show progress dialog while invites are being sent * Add new ProgressDialog previews to the naming exceptions list * Update screenshots --------- Co-authored-by: ElementBot Co-authored-by: Jorge Martín --- .../invitepeople/api/InvitePeopleState.kt | 3 ++ .../api/InvitePeopleStateProvider.kt | 7 ++- .../impl/DefaultInvitePeoplePresenter.kt | 30 +++++++---- .../impl/DefaultInvitePeopleState.kt | 2 + .../impl/DefaultInvitePeopleStateProvider.kt | 8 +++ .../impl/DefaultInvitePeoplePresenterTest.kt | 26 +++++++++ .../impl/invite/RoomInviteMembersNode.kt | 12 ++++- .../impl/invite/RoomInviteMembersView.kt | 32 +++++++++-- .../impl/src/main/res/values/localazy.xml | 2 + .../designsystem/components/ProgressDialog.kt | 53 +++++++++++++++++-- .../src/main/res/values/localazy.xml | 1 + .../tests/konsist/KonsistPreviewTest.kt | 2 + ....impl.addpeople_AddPeopleView_Day_3_en.png | 3 ++ ...mpl.addpeople_AddPeopleView_Night_3_en.png | 3 ++ ...epeople.impl_InvitePeopleView_Day_9_en.png | 3 ++ ...eople.impl_InvitePeopleView_Night_9_en.png | 3 ++ ....invite_RoomInviteMembersView_Day_3_en.png | 3 ++ ...nvite_RoomInviteMembersView_Night_3_en.png | 3 ++ ...nts_ProgressDialogWithContent_Day_0_en.png | 3 ++ ...s_ProgressDialogWithContent_Night_0_en.png | 3 ++ ...gressDialogWithTextAndContent_Day_0_en.png | 3 ++ ...essDialogWithTextAndContent_Night_0_en.png | 3 ++ 22 files changed, 189 insertions(+), 19 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.createroom.impl.addpeople_AddPeopleView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.createroom.impl.addpeople_AddPeopleView_Night_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_9_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_9_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithContent_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithTextAndContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithTextAndContent_Night_0_en.png diff --git a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt index db8b9ffbd2..75fd211295 100644 --- a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt +++ b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt @@ -7,8 +7,11 @@ package io.element.android.features.invitepeople.api +import io.element.android.libraries.architecture.AsyncAction + interface InvitePeopleState { val canInvite: Boolean val isSearchActive: Boolean + val sendInvitesAction: AsyncAction val eventSink: (InvitePeopleEvents) -> Unit } diff --git a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleStateProvider.kt b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleStateProvider.kt index b69ad7c225..fdcebb17a2 100644 --- a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleStateProvider.kt +++ b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleStateProvider.kt @@ -8,28 +8,33 @@ package io.element.android.features.invitepeople.api import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.AsyncAction class InvitePeopleStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aPreviewInvitePeopleState(), aPreviewInvitePeopleState(canInvite = true), - aPreviewInvitePeopleState(isSearchActive = true) + aPreviewInvitePeopleState(isSearchActive = true), + aPreviewInvitePeopleState(sendInvitesAction = AsyncAction.Loading), ) } private data class PreviewInvitePeopleState( override val canInvite: Boolean, override val isSearchActive: Boolean, + override val sendInvitesAction: AsyncAction, override val eventSink: (InvitePeopleEvents) -> Unit, ) : InvitePeopleState private fun aPreviewInvitePeopleState( canInvite: Boolean = false, isSearchActive: Boolean = false, + sendInvitesAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (InvitePeopleEvents) -> Unit = {}, ) = PreviewInvitePeopleState( canInvite = canInvite, isSearchActive = isSearchActive, + sendInvitesAction = sendInvitesAction, eventSink = eventSink ) diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt index e473f5708b..2ce5cd929a 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt @@ -23,9 +23,11 @@ import dev.zacsweers.metro.Inject import io.element.android.features.invitepeople.api.InvitePeopleEvents import io.element.android.features.invitepeople.api.InvitePeoplePresenter import io.element.android.features.invitepeople.api.InvitePeopleState +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.map import io.element.android.libraries.architecture.runCatchingUpdatingState +import io.element.android.libraries.architecture.runUpdatingState import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.di.SessionScope @@ -73,6 +75,8 @@ class DefaultInvitePeoplePresenter( var searchQuery by rememberSaveable { mutableStateOf("") } var searchActive by rememberSaveable { mutableStateOf(false) } val showSearchLoader = rememberSaveable { mutableStateOf(false) } + val sendInvitesAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } + val room by produceState(if (joinedRoom != null) AsyncData.Success(joinedRoom) else AsyncData.Loading()) { if (joinedRoom == null) { val result = matrixClient.getJoinedRoom(roomId) @@ -116,7 +120,7 @@ class DefaultInvitePeoplePresenter( } is InvitePeopleEvents.SendInvites -> { room.dataOrNull()?.let { - sessionCoroutineScope.sendInvites(it, selectedUsers.value) + sessionCoroutineScope.sendInvites(it, selectedUsers.value, sendInvitesAction) } } is InvitePeopleEvents.CloseSearch -> { @@ -128,12 +132,13 @@ class DefaultInvitePeoplePresenter( return DefaultInvitePeopleState( room = room.map { }, - canInvite = selectedUsers.value.isNotEmpty(), + canInvite = selectedUsers.value.isNotEmpty() && !sendInvitesAction.value.isLoading(), selectedUsers = selectedUsers.value, searchQuery = searchQuery, isSearchActive = searchActive, searchResults = searchResults.value, showSearchLoader = showSearchLoader.value, + sendInvitesAction = sendInvitesAction.value, eventSink = ::handleEvents, ) } @@ -141,16 +146,21 @@ class DefaultInvitePeoplePresenter( private fun CoroutineScope.sendInvites( room: JoinedRoom, selectedUsers: List, + sendInvitesAction: MutableState>, ) = launch { - val anyInviteFailed = selectedUsers - .map { room.inviteUserById(it.userId) } - .any { it.isFailure } + sendInvitesAction.runUpdatingState { + val anyInviteFailed = selectedUsers + .map { room.inviteUserById(it.userId) } + .any { it.isFailure } - if (anyInviteFailed) { - appErrorStateService.showError( - titleRes = CommonStrings.common_unable_to_invite_title, - bodyRes = CommonStrings.common_unable_to_invite_message, - ) + if (anyInviteFailed) { + appErrorStateService.showError( + titleRes = CommonStrings.common_unable_to_invite_title, + bodyRes = CommonStrings.common_unable_to_invite_message, + ) + } + + Result.success(Unit) } } diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleState.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleState.kt index 77ba8aad05..5ae51a8698 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleState.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleState.kt @@ -9,6 +9,7 @@ package io.element.android.features.invitepeople.impl import io.element.android.features.invitepeople.api.InvitePeopleEvents import io.element.android.features.invitepeople.api.InvitePeopleState +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.api.user.MatrixUser @@ -22,5 +23,6 @@ data class DefaultInvitePeopleState( val searchResults: SearchBarResultState>, val selectedUsers: ImmutableList, override val isSearchActive: Boolean, + override val sendInvitesAction: AsyncAction, override val eventSink: (InvitePeopleEvents) -> Unit ) : InvitePeopleState diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt index 980d32e7fb..ebcd932a55 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt @@ -8,6 +8,7 @@ package io.element.android.features.invitepeople.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.api.user.MatrixUser @@ -68,6 +69,11 @@ internal class DefaultInvitePeopleStateProvider : PreviewParameterProvider = persistentListOf(), isSearchActive: Boolean = false, showSearchLoader: Boolean = false, + sendInvitesAction: AsyncAction = AsyncAction.Uninitialized, ): DefaultInvitePeopleState { return DefaultInvitePeopleState( room = room, @@ -102,6 +109,7 @@ private fun aDefaultInvitePeopleState( selectedUsers = selectedUsers, isSearchActive = isSearchActive, showSearchLoader = showSearchLoader, + sendInvitesAction = sendInvitesAction, eventSink = {}, ) } diff --git a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt index 1e438fab8e..e51c3ee352 100644 --- a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt +++ b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt @@ -409,10 +409,23 @@ internal class DefaultInvitePeoplePresenterTest { assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) // Send invites initialState.eventSink(InvitePeopleEvents.SendInvites) + + // Can't invite in the loading state + awaitItem().run { + assertThat(sendInvitesAction.isLoading()).isTrue() + assertThat(canInvite).isFalse() + } + delay(1_000) inviteUserResult.assertions().isCalledOnce().with( value(selectedUser.userId) ) + + // Can invite again once the action is finished + awaitItem().run { + assertThat(sendInvitesAction.isReady()).isTrue() + assertThat(canInvite).isTrue() + } } } @@ -445,6 +458,13 @@ internal class DefaultInvitePeoplePresenterTest { assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) // Send invites initialState.eventSink(InvitePeopleEvents.SendInvites) + + // Can't invite in the loading state + awaitItem().run { + assertThat(sendInvitesAction.isLoading()).isTrue() + assertThat(canInvite).isFalse() + } + delay(1_000) inviteUserResult.assertions().isCalledOnce().with( value(selectedUser.userId) @@ -455,6 +475,12 @@ internal class DefaultInvitePeoplePresenterTest { value(CommonStrings.common_unable_to_invite_title), value(CommonStrings.common_unable_to_invite_message) ) + + // Can invite again once the action is finished + awaitItem().run { + assertThat(sendInvitesAction.isReady()).isTrue() + assertThat(canInvite).isTrue() + } } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersNode.kt index 6c69f0ee5d..04b98e3d98 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersNode.kt @@ -8,6 +8,7 @@ package io.element.android.features.roomdetails.impl.invite import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import com.bumble.appyx.core.lifecycle.subscribe import com.bumble.appyx.core.modality.BuildContext @@ -49,11 +50,18 @@ class RoomInviteMembersNode( @Composable override fun View(modifier: Modifier) { val state = invitePeoplePresenter.present() + + // Once invites have been sent successfully, close the Invite view. + LaunchedEffect(state.sendInvitesAction) { + if (state.sendInvitesAction.isReady()) { + navigateUp() + } + } + RoomInviteMembersView( state = state, modifier = modifier, - onBackClick = { navigateUp() }, - onDone = { navigateUp() } + onBackClick = { navigateUp() } ) { invitePeopleRenderer.Render(state, Modifier) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt index 8bec90707f..f7991a6e44 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt @@ -8,22 +8,29 @@ package io.element.android.features.roomdetails.impl.invite import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme import io.element.android.features.invitepeople.api.InvitePeopleEvents import io.element.android.features.invitepeople.api.InvitePeopleState import io.element.android.features.invitepeople.api.InvitePeopleStateProvider import io.element.android.features.roomdetails.impl.R +import io.element.android.libraries.designsystem.components.ProgressDialog 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.Text import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.ui.strings.CommonStrings @@ -32,7 +39,6 @@ import io.element.android.libraries.ui.strings.CommonStrings fun RoomInviteMembersView( state: InvitePeopleState, onBackClick: () -> Unit, - onDone: () -> Unit, modifier: Modifier = Modifier, invitePeopleView: @Composable () -> Unit, ) { @@ -49,7 +55,6 @@ fun RoomInviteMembersView( }, onSubmitClick = { state.eventSink(InvitePeopleEvents.SendInvites) - onDone() }, canSend = state.canInvite, ) @@ -64,6 +69,10 @@ fun RoomInviteMembersView( invitePeopleView() } } + + if (state.sendInvitesAction.isLoading()) { + InviteProgressDialog() + } } @OptIn(ExperimentalMaterial3Api::class) @@ -86,6 +95,24 @@ private fun RoomInviteMembersTopBar( ) } +@Composable +private fun InviteProgressDialog() { + ProgressDialog { + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = stringResource(R.string.screen_room_details_invite_people_preparing), + color = ElementTheme.colors.textPrimary, + style = ElementTheme.typography.fontHeadingSmMedium, + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = stringResource(R.string.screen_room_details_invite_people_dont_close), + color = ElementTheme.colors.textSecondary, + style = MaterialTheme.typography.bodyMedium, + ) + } +} + @PreviewsDayNight @Composable internal fun RoomInviteMembersViewPreview(@PreviewParameter(InvitePeopleStateProvider::class) state: InvitePeopleState) = ElementPreview { @@ -93,6 +120,5 @@ internal fun RoomInviteMembersViewPreview(@PreviewParameter(InvitePeopleStatePro state = state, invitePeopleView = {}, onBackClick = {}, - onDone = {}, ) } diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index 5dd185ec13..3f4541dacb 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -50,6 +50,8 @@ "An error occurred when loading notification settings." "Failed muting this room, please try again." "Failed unmuting this room, please try again." + "Don\'t close the app until finished." + "Preparing invitations…" "Invite people" "Leave conversation" "Leave room" diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ProgressDialog.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ProgressDialog.kt index f5d8a50ce0..fe18daaaea 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ProgressDialog.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ProgressDialog.kt @@ -38,6 +38,18 @@ import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.ui.strings.CommonStrings import timber.log.Timber +/** + * A progress dialog, with a spinner, and optional text content. + * + * @param modifier + * @param text Optional text to show under the spinner. + * @param type + * @param properties + * @param showCancelButton + * @param onDismissRequest + * @param content Optional additional content to show under the spinner, and above the cancel button (if shown). If both `text` and `content` are supplied, + * `text` is shown above `content`. + */ @Composable fun ProgressDialog( modifier: Modifier = Modifier, @@ -46,6 +58,7 @@ fun ProgressDialog( properties: DialogProperties = DialogProperties(dismissOnBackPress = false, dismissOnClickOutside = false), showCancelButton: Boolean = false, onDismissRequest: () -> Unit = {}, + content: @Composable () -> Unit = {}, ) { DisposableEffect(Unit) { onDispose { @@ -75,7 +88,8 @@ fun ProgressDialog( ) } } - } + }, + content, ) } } @@ -96,7 +110,8 @@ private fun ProgressDialogContent( CircularProgressIndicator( color = ElementTheme.colors.iconPrimary ) - } + }, + content: @Composable () -> Unit, ) { Box( contentAlignment = Alignment.Center, @@ -118,6 +133,7 @@ private fun ProgressDialogContent( color = ElementTheme.colors.textPrimary, ) } + content() if (showCancelButton) { Spacer(modifier = Modifier.height(24.dp)) Box( @@ -138,7 +154,7 @@ private fun ProgressDialogContent( @Composable internal fun ProgressDialogContentPreview() = ElementThemedPreview { DialogPreview { - ProgressDialogContent(text = "test dialog content", showCancelButton = true) + ProgressDialogContent(text = "test dialog content", showCancelButton = true, content = {}) } } @@ -147,3 +163,34 @@ internal fun ProgressDialogContentPreview() = ElementThemedPreview { internal fun ProgressDialogPreview() = ElementPreview { ProgressDialog(text = "test dialog content", showCancelButton = true) } + +@PreviewsDayNight +@Composable +internal fun ProgressDialogWithContentPreview() = ElementPreview { + ProgressDialog(showCancelButton = true) { + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = "Heading", + color = ElementTheme.colors.textPrimary, + style = ElementTheme.typography.fontHeadingSmMedium, + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = "Subtext", + color = ElementTheme.colors.textSecondary, + style = MaterialTheme.typography.bodyMedium, + ) + } +} + +@PreviewsDayNight +@Composable +internal fun ProgressDialogWithTextAndContentPreview() = ElementPreview { + ProgressDialog(text = "Text Content") { + Text( + text = "blah blah", + color = ElementTheme.colors.textPrimary, + style = ElementTheme.typography.fontHeadingSmMedium, + ) + } +} diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index c7694387a6..49c54a91cd 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -304,6 +304,7 @@ Reason: %1$s." "Sent" ". " "Server not supported" + "Server unreachable" "Server URL" "Settings" "Shared location" 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 d0408fb61a..9cbd2efdc4 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 @@ -114,6 +114,8 @@ class KonsistPreviewTest { "PollContentViewDisclosedPreview", "PollContentViewEndedPreview", "PollContentViewUndisclosedPreview", + "ProgressDialogWithContentPreview", + "ProgressDialogWithTextAndContentPreview", "ReadReceiptBottomSheetPreview", "RoomMemberListViewBannedPreview", "SasEmojisPreview", diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.addpeople_AddPeopleView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.addpeople_AddPeopleView_Day_3_en.png new file mode 100644 index 0000000000..338eb8d3f6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.addpeople_AddPeopleView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7415b3286707130c0218a8d1e82a9d9c61c8eec8df346653dd67626d0dd7709c +size 10038 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.addpeople_AddPeopleView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.addpeople_AddPeopleView_Night_3_en.png new file mode 100644 index 0000000000..5bd1590652 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.addpeople_AddPeopleView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39c67413ca997982b0fcd32831ccedee1d7a0763619784b8758b194df6c7ff81 +size 9639 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_9_en.png new file mode 100644 index 0000000000..1e3446160f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94341fe8aa52b4551ef8a73cf298aaa1c4352ae0d4c83990c04c4c6e491b64e8 +size 21444 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_9_en.png new file mode 100644 index 0000000000..2de946c312 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00a961c76598dc98a0d9c7a45781865984c51bb440bb1605c381e9496ca1789f +size 21971 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en.png new file mode 100644 index 0000000000..1f179c4be8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a809a8792d519f93df9a15c57c06d3fd4f3cb7c84245e80cf61ff07ab1c5d620 +size 20363 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en.png new file mode 100644 index 0000000000..f326451237 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:433e3467cfa0c0f4e737ec15a1c41d6bbc36d4d2c2dd9f2f7f22bb457208f280 +size 19180 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithContent_Day_0_en.png new file mode 100644 index 0000000000..d4ef5f016f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b637e70da73ea0fca81adb861abf69fb2092d35493417fb29103f5acebf6fa0 +size 11706 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithContent_Night_0_en.png new file mode 100644 index 0000000000..7e648f0530 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:440b6f0e84c9fccfbbc997a40e1e8459df1962218fa4fdceb7ea8ecc8c96090b +size 11442 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithTextAndContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithTextAndContent_Day_0_en.png new file mode 100644 index 0000000000..b58b42b2d6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithTextAndContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3212b09963d5fa9b89b1ebfd8f904b3f436399299e67f560f39620d063eb997 +size 11408 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithTextAndContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithTextAndContent_Night_0_en.png new file mode 100644 index 0000000000..a534eae610 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_ProgressDialogWithTextAndContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae69faa0c95f4ae4b7b410da438f0e3992571c21837e644e63621fa1f73e297a +size 11220 From 874fd668bd7c729aba51d0e73d2f7cabe5acc4ba Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 Sep 2025 19:09:55 +0200 Subject: [PATCH 043/145] Update dependency com.google.testparameterinjector:test-parameter-injector to v1.19 (#5341) 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 8b79d99011..ca2f436f54 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -153,7 +153,7 @@ test_mockk = "io.mockk:mockk:1.14.5" test_konsist = "com.lemonappdev:konsist:0.17.3" test_turbine = "app.cash.turbine:turbine:1.2.1" test_truth = "com.google.truth:truth:1.4.5" -test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.18" +test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.19" test_robolectric = "org.robolectric:robolectric:4.15.1" test_appyx_junit = { module = "com.bumble.appyx:testing-junit4", version.ref = "appyx" } test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.7.0" From 93cbe24ab4768659064ee572fe5139e328c2356d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 05:15:47 +0000 Subject: [PATCH 044/145] Update telephoto to v0.17.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 ca2f436f54..e9cf072918 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -44,7 +44,7 @@ showkase = "1.0.5" appyx = "1.7.1" sqldelight = "2.1.0" wysiwyg = "2.39.0" -telephoto = "0.16.0" +telephoto = "0.17.0" haze = "1.6.10" # Dependency analysis From 23cb08412663d0bc47004ce1e2144d88d0f772f4 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 15 Sep 2025 08:39:59 +0200 Subject: [PATCH 045/145] Sync Strings from Localazy (#5349) Co-authored-by: bmarty <3940906+bmarty@users.noreply.github.com> --- .../src/main/res/values-pt/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 3 +- .../src/main/res/values-pt/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 2 +- .../src/main/res/values-fi/translations.xml | 3 + .../src/main/res/values-fi/translations.xml | 4 + .../src/main/res/values-de/translations.xml | 2 + .../src/main/res/values-et/translations.xml | 2 + .../src/main/res/values-pt/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 4 +- .../src/main/res/values-da/translations.xml | 9 +- .../src/main/res/values-de/translations.xml | 7 + .../src/main/res/values-et/translations.xml | 6 + .../src/main/res/values-fi/translations.xml | 13 +- .../src/main/res/values-pt/translations.xml | 19 +- .../src/main/res/values-uz/translations.xml | 1 + .../src/main/res/values-zh/translations.xml | 8 +- .../src/main/res/values/localazy.xml | 5 + ....impl.addpeople_AddPeopleView_Day_3_de.png | 3 + ...impl.spaces_HomeSpaceItemView_Day_0_de.png | 3 - ...impl.spaces_HomeSpaceItemView_Day_1_de.png | 3 - ...impl.spaces_HomeSpaceItemView_Day_2_de.png | 3 - ...impl.spaces_HomeSpaceItemView_Day_3_de.png | 3 - ...impl.spaces_HomeSpaceItemView_Day_4_de.png | 3 - ...me.impl.spaces_HomeSpacesView_Day_0_de.png | 4 +- ...epeople.impl_InvitePeopleView_Day_9_de.png | 3 + ....invite_RoomInviteMembersView_Day_3_de.png | 3 + ...features.space.impl_SpaceView_Day_2_de.png | 3 + ...features.space.impl_SpaceView_Day_3_de.png | 3 + ...nts_ProgressDialogWithContent_Day_0_de.png | 3 + screenshots/html/data.js | 1754 +++++++++-------- 34 files changed, 983 insertions(+), 908 deletions(-) create mode 100644 screenshots/de/features.createroom.impl.addpeople_AddPeopleView_Day_3_de.png delete mode 100644 screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_0_de.png delete mode 100644 screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_1_de.png delete mode 100644 screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_2_de.png delete mode 100644 screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_3_de.png delete mode 100644 screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_4_de.png create mode 100644 screenshots/de/features.invitepeople.impl_InvitePeopleView_Day_9_de.png create mode 100644 screenshots/de/features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_de.png create mode 100644 screenshots/de/features.space.impl_SpaceView_Day_2_de.png create mode 100644 screenshots/de/features.space.impl_SpaceView_Day_3_de.png create mode 100644 screenshots/de/libraries.designsystem.components_ProgressDialogWithContent_Day_0_de.png diff --git a/appnav/src/main/res/values-pt/translations.xml b/appnav/src/main/res/values-pt/translations.xml index d606a8d103..2d84d29475 100644 --- a/appnav/src/main/res/values-pt/translations.xml +++ b/appnav/src/main/res/values-pt/translations.xml @@ -2,5 +2,5 @@ "Sair & Atualizar" "%1$s já não suporta o protocolo antigo. Termina a sessão e volta a iniciar sessão para continuares a utilizar a aplicação." - "Seu homeserver não suporta mais o protocolo antigo. Termine sessão e volte a iniciar sessão para continuar a utilizar a aplicação." + "O teu servidor já não permite o protocolo antigo. Termine sessão e volte a iniciá-la para continuar a utilizar a aplicação." diff --git a/features/deactivation/impl/src/main/res/values-pt/translations.xml b/features/deactivation/impl/src/main/res/values-pt/translations.xml index 536f4cec34..0a8c618e44 100644 --- a/features/deactivation/impl/src/main/res/values-pt/translations.xml +++ b/features/deactivation/impl/src/main/res/values-pt/translations.xml @@ -1,6 +1,6 @@ - "Confirme que pretende desativar a sua conta. Esta ação não pode ser desfeita." + "Confirma que pretendes desativar a tua conta. Esta ação não pode ser desfeita." "Eliminar todas as minhas mensagens" "Aviso: futuros usuários podem ver conversas incompletas." "A desativação da sua conta é %1$s, irá:" diff --git a/features/home/impl/src/main/res/values-pt/translations.xml b/features/home/impl/src/main/res/values-pt/translations.xml index 2a63000ea0..6c9f5a6fbd 100644 --- a/features/home/impl/src/main/res/values-pt/translations.xml +++ b/features/home/impl/src/main/res/values-pt/translations.xml @@ -16,7 +16,7 @@ "Espaços" "Tens a certeza que queres rejeitar o convite para entra em %1$s?" "Rejeitar convite" - "Tem a certeza que queres rejeitar esta conversa privada com %1$s?" + "Tens a certeza que queres rejeitar esta conversa privada com %1$s?" "Rejeitar conversa" "Sem convites" "%1$s (%2$s) convidou-te" @@ -33,6 +33,7 @@ Por enquanto, podes anular a seleção dos filtros para veres as tuas outras con "Convites" "Não tens nenhum convite pendente." "Prioridade baixa" + "Ainda não tens conversas de prioridade baixa" "Podes anular a seleção dos filtros para veres as tuas outras conversas" "Não tens nenhuma conversa selecionada" "Pessoas" diff --git a/features/invite/impl/src/main/res/values-pt/translations.xml b/features/invite/impl/src/main/res/values-pt/translations.xml index 34804068a8..513f14eea6 100644 --- a/features/invite/impl/src/main/res/values-pt/translations.xml +++ b/features/invite/impl/src/main/res/values-pt/translations.xml @@ -7,7 +7,7 @@ "Rejeitar e bloquear" "Tens a certeza que queres rejeitar o convite para entra em %1$s?" "Rejeitar convite" - "Tem a certeza que queres rejeitar esta conversa privada com %1$s?" + "Tens a certeza que queres rejeitar esta conversa privada com %1$s?" "Rejeitar conversa" "Sem convites" "%1$s (%2$s) convidou-te" diff --git a/features/joinroom/impl/src/main/res/values-pt/translations.xml b/features/joinroom/impl/src/main/res/values-pt/translations.xml index 695d3124c3..5bac83b9d2 100644 --- a/features/joinroom/impl/src/main/res/values-pt/translations.xml +++ b/features/joinroom/impl/src/main/res/values-pt/translations.xml @@ -20,7 +20,7 @@ "Bater à porta" "%1$d de %2$d caracteres permitidos" "Mensagem (opcional)" - "Irá receber um convite para participar na sala se seu pedido for aceite." + "Irás receber um convite para participar na sala se o pedido for aceite." "Pedido de adesão enviado" "Não conseguimos exibir a pré-visualização da sala. Isso pode ser devido a problemas de rede ou servidor." "Não foi possível exibir a pré-visualização desta sala" diff --git a/features/login/impl/src/main/res/values-pt/translations.xml b/features/login/impl/src/main/res/values-pt/translations.xml index 08bacffa92..a2a7bdc688 100644 --- a/features/login/impl/src/main/res/values-pt/translations.xml +++ b/features/login/impl/src/main/res/values-pt/translations.xml @@ -74,7 +74,7 @@ Tenta iniciar a sessão manualmente ou digitaliza o código QR com outro disposi "Seleciona %1$s" "“Ligar novo dispositivo”" "Lê o código QR com este dispositivo" - "Disponível apenas se o seu fornecedor de conta o suportar." + "Disponível apenas se o teu operador de conta o permitir." "Abre a %1$s noutro dispositivo para obteres o código QR" "Lê o código QR apresentado no outro dispositivo." "Tentar novamente" diff --git a/features/messages/impl/src/main/res/values-fi/translations.xml b/features/messages/impl/src/main/res/values-fi/translations.xml index 0f4a273f0f..814c2cd5c2 100644 --- a/features/messages/impl/src/main/res/values-fi/translations.xml +++ b/features/messages/impl/src/main/res/values-fi/translations.xml @@ -9,11 +9,14 @@ "Matkustaminen ja paikat" "Symbolit" "Kuvatekstit eivät välttämättä näy ihmisille, jotka käyttävät vanhempia sovelluksia." + "Napauta muuttaaksesi videon lähetyslaatua" "Tiedostoa ei voitu lähettää." "Median käsittely epäonnistui, yritä uudelleen." "Median lähettäminen epäonnistui, yritä uudelleen." "Suurin sallittu tiedostokoko on %1$s." "Tiedosto on liian suuri lähetettäväksi" + "Optimoi kuvanlaatu" + "Käsitellään…" "Estä käyttäjä" "Valitse tämä, jos haluat piilottaa kaikki nykyiset ja tulevat viestit tältä käyttäjältä" "Tämä viesti ilmoitetaan kotipalvelimesi ylläpitäjälle. Ylläpitäjä ei pysty lukemaan salattuja viestejä." diff --git a/features/preferences/impl/src/main/res/values-fi/translations.xml b/features/preferences/impl/src/main/res/values-fi/translations.xml index f938235e66..19c87492fb 100644 --- a/features/preferences/impl/src/main/res/values-fi/translations.xml +++ b/features/preferences/impl/src/main/res/values-fi/translations.xml @@ -13,6 +13,10 @@ "Lähetä valokuvia ja videoita nopeammin ja vähennä datan käyttöä." "Optimoi median laatu" "Moderointi ja Turvallisuus" + "Optimoi kuvat automaattisesti nopeampia lähetysnopeuksia ja pienempiä tiedostokokoja varten." + "Optimoi kuvien lähetyslaatu" + "%1$s. Napauta tästä vaihtaaksesi." + "Videon lähetyslaatu" "Push-ilmoitusten tarjoaja" "Ota rikastettu tekstieditori pois käytöstä, jotta voit kirjoittaa Markdownia manuaalisesti." "Lukukuittaukset" diff --git a/features/roomdetails/impl/src/main/res/values-de/translations.xml b/features/roomdetails/impl/src/main/res/values-de/translations.xml index 3bf75e97e2..4a4f8a44b6 100644 --- a/features/roomdetails/impl/src/main/res/values-de/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-de/translations.xml @@ -50,6 +50,8 @@ "Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." "Die Stummschaltung ist fehlgeschlagen, bitte versuche es erneut." "Die Deaktivierung der Stummschaltung ist fehlgeschlagen, bitte versuche es erneut." + "Schließ die App erst, wenn du fertig bist." + "Einladungen werden vorbereitet…" "Nutzer einladen" "Unterhaltung verlassen" "Verlassen" diff --git a/features/roomdetails/impl/src/main/res/values-et/translations.xml b/features/roomdetails/impl/src/main/res/values-et/translations.xml index 4426ca1e77..6de3107def 100644 --- a/features/roomdetails/impl/src/main/res/values-et/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-et/translations.xml @@ -50,6 +50,8 @@ "Teavituste seadistuste laadimisel tekkis viga." "Selle jututoa summutamine ei õnnestunud. Palun proovi uuesti." "Selle jututoa summutamise eemaldamine ei õnnestunud. Palun proovi uuesti." + "Ära sulge rakendust enne, kui tegevus on lõppenud." + "Valmistan kutseid ette…" "Kutsu osalejaid" "Lahku vestlusest" "Lahku jututoast" diff --git a/features/userprofile/shared/src/main/res/values-pt/translations.xml b/features/userprofile/shared/src/main/res/values-pt/translations.xml index eae68be0b7..ec919a456a 100644 --- a/features/userprofile/shared/src/main/res/values-pt/translations.xml +++ b/features/userprofile/shared/src/main/res/values-pt/translations.xml @@ -14,6 +14,6 @@ "Poderás voltar a ver todas as suas mensagens." "Desbloquear utilizador" "Utiliza a aplicação Web para verificar este utilizador." - "Verifique %1$s" + "Verifica %1$s" "Ocorreu um erro ao tentar iniciar uma conversa" 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 1386091254..ce2eb2af15 100644 --- a/features/verifysession/impl/src/main/res/values-pt/translations.xml +++ b/features/verifysession/impl/src/main/res/values-pt/translations.xml @@ -30,7 +30,7 @@ "Sessão iniciada" "O pedido expirou, o pedido foi recusado ou houve um erro de verificação." "A verificação falhou" - "Continue apenas se tiver iniciado esta verificação." + "Continua apenas se tiveres iniciado esta verificação." "Verifique o outro dispositivo para manter o histórico de mensagens seguro." "Agora podes ler ou enviar mensagens de forma segura no teu outro dispositivo." "Dispositivo verificado" diff --git a/libraries/push/impl/src/main/res/values-pt/translations.xml b/libraries/push/impl/src/main/res/values-pt/translations.xml index 0a55a1dd7b..c62a951fa6 100644 --- a/libraries/push/impl/src/main/res/values-pt/translations.xml +++ b/libraries/push/impl/src/main/res/values-pt/translations.xml @@ -23,7 +23,7 @@ "%d convites" "Convidou-te para conversar" - "%1$s convidou-o para conversar" + "%1$s convidou-te para conversar" "Mencionou-te: %1$s" "Mensagens novas" @@ -34,7 +34,7 @@ "Marcar como lida" "Resposta rápida" "Convidou-te a entrar na sala" - "%1$s convidou-o a juntar-se à sala" + "%1$s convidou-te a entrares na sala" "Eu" "%1$s mencionou ou respondeu" "Estás a ver a notificação! Clica em mim!" diff --git a/libraries/ui-strings/src/main/res/values-da/translations.xml b/libraries/ui-strings/src/main/res/values-da/translations.xml index 4116bfa8f1..44f0321315 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -42,7 +42,7 @@ "Fjern reaktion med %1$s" "Avatar for rummet" "Send filer" - "Tidsbegrænset handling påkrævet" + "Tidsbegrænset handling påkrævet, du har et minut til at bekræfte" "Vis adgangskode" "Start et opkald" "Deaktiveret rum" @@ -165,6 +165,8 @@ "Opgradering tilgængelig" "Om" "Politik for acceptabel brug" + "Tilføj en konto" + "Tilføj en anden konto" "Tilføjelse af billedtekst" "Avancerede indstillinger" "et billede" @@ -185,6 +187,7 @@ "Invitationen blev afvist" "Mørkt tema" "Fejl under dekryptering" + "Beskrivelse" "Indstillinger for udviklere" "Enheds-ID" "Direkte samtale" @@ -293,12 +296,14 @@ "Søgeresultater" "Sikkerhed" "Set af" + "Vælg en konto" "Send til" "Sender…" "Afsendelse mislykkedes" "Sendt" ". " "Serveren er ikke understøttet" + "Serveren er ikke tilgængelig" "Server URL" "Indstillinger" "Delt placering" @@ -375,6 +380,8 @@ Er du sikker på, at du vil fortsætte?" "Den maksimalt tilladte filstørrelse er: %1$s" "Vælg den kvalitet, du ønsker at uploade videoen i." "Vælg kvalitet for video-overførsel" + "Søg emojis" + "Du er allerede logget ind på denne enhed som %1$s." "Din hjemmeserver skal opgraderes for at understøtte Matrix Authentication Service og kontooprettelse." "Oprettelse af permalink mislykkedes" "%1$s kunne ikke indlæse kortet. Prøv igen senere." 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 82fe401127..39396928eb 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -105,6 +105,7 @@ "Verlassen" "Unterhaltung verlassen" "Verlassen" + "Space verlassen" "Mehr laden…" "Konto verwalten" "Geräte verwalten" @@ -184,9 +185,11 @@ "Chat wird erstellt…" "Anfrage abgebrochen" "Hat den Chat verlassen" + "Space verlassen" "Einladung abgelehnt" "Dunkel" "Dekodierungsfehler" + "Beschreibung" "Entwickleroptionen" "Geräte-ID" "Direktnachricht" @@ -303,6 +306,7 @@ Grund: %1$s." "Gesendet" ". " "Server wird nicht unterstützt" + "Server nicht erreichbar" "Server-URL" "Einstellungen" "Geteilter Standort" @@ -408,6 +412,9 @@ Möchtest du wirklich fortfahren?" "Hey, sprich mit mir auf %1$s: %2$s" "%1$s Android" "Heftiges Schütteln um Fehler zu melden" + "Dadurch wirst du auch aus allen Chats in diesem Space entfernt." + "Dadurch wirst du auch aus allen Chats in diesem Space entfernt, auch aus denen, für die du der einzige Admin bist:" + "%1$s verlassen?" "Bildschirmfoto" "%1$s: %2$s" "Optionen" 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 cd74b0061e..e02bba3558 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -105,6 +105,7 @@ "Lahku" "Lahku vestlusest" "Lahku jututoast" + "Lahku kogukonnast" "Näita veel" "Halda kasutajakontot" "Halda seadmeid" @@ -187,6 +188,7 @@ "Keeldusid kutsest" "Tume" "Dekrüptimisviga" + "Kirjeldus" "Arendaja valikud" "Seadme tunnus" "Otsevestlus" @@ -303,6 +305,7 @@ Põhjus: %1$s." "Saadetud" ". " "Server pole toetatud" + "Server pole leitav" "Serveri URL" "Seadistused" "Jagatud asukoht" @@ -408,6 +411,9 @@ Kas sa oled kindel, et soovid jätkata?" "Hei, suhtle minuga %1$s võrgus: %2$s" "%1$s Android" "Veast teatamiseks raputa nutiseadet ägedalt" + "Sellega eemaldad end ka kõikidest antud kogukonna jututubadest." + "Sellega eemaldad end ka kõikidest antud kogukonna jututubadest, sealhulgast järgnevaist, kus oled ainus peakasutaja:" + "Kas lahkud %1$s kogukonnast?" "Ekraanitõmmis" "%1$s: %2$s" "Valikud" diff --git a/libraries/ui-strings/src/main/res/values-fi/translations.xml b/libraries/ui-strings/src/main/res/values-fi/translations.xml index 4b2fe2682f..e41c83ea73 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -40,7 +40,7 @@ "Poista reaktio: %1$s" "Huoneen avatar" "Lähetä tiedostoja" - "Aikarajoitettu toimenpide vaaditaan" + "Aikarajoitettu toimenpide vaaditaan, sinulla on yksi minuutti aikaa vahvistaa" "Näytä salasana" "Aloita puhelu" "Haudattu huone" @@ -335,6 +335,12 @@ Syy: %1$s." "Vahvista identiteetti" "Vahvista käyttäjä" "Video" + "Korkea laatu" + "Paras laatu, mutta suurempi tiedostokoko" + "Heikko laatu" + "Nopein lähetysnopeus ja pienin tiedostokoko" + "Normaali laatu" + "Tasapainotettu laatu ja lähetysnopeus" "Ääniviesti" "Odotetaan…" "Odotetaan viestiä" @@ -349,6 +355,8 @@ Syy: %1$s." Haluatko varmasti jatkaa?" "Tarkista tämä linkki" + "Suurin sallittu tiedostokoko on: %1$s" + "Tiedostokoko on liian suuri lähetettäväksi" "Huone ilmoitettu" "Ilmoitettu ja poistuttu huoneesta" "Vahvistus" @@ -357,6 +365,9 @@ Haluatko varmasti jatkaa?" "Varoitus" "Muutoksiasi ei ole tallennettu. Haluatko varmasti palata takaisin?" "Tallenna muutokset?" + "Suurin sallittu tiedostokoko on: %1$s" + "Valitse lähetettävän videon laatu." + "Valitse videon lähetyslaatu" "Kotipalvelimesi on päivitettävä tukemaan Matrix Authentication Serviceä ja tilin luomista." "Pysyvän linkin luominen epäonnistui" "%1$s ei pystynyt lataamaan karttaa. Yritä myöhemmin uudelleen." 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 592c1f9961..0675f6e86d 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -2,6 +2,7 @@ "Adicionar reação: %1$s" "Avatar" + "Minimizar campo de texto da mensagem" "Eliminar" "%1$d dígito inserido" @@ -10,6 +11,7 @@ "Editar avatar" "O endereço completo será %1$s" "Detalhes de cifragem" + "Expandir campo de texto da mensagem" "Ocultar palavra-passe" "Juntar-se à chamada" "Saltar para o fundo" @@ -40,7 +42,7 @@ "Remover reação com %1$s" "Ícone da sala" "Enviar ficheiros" - "Necessária ação em tempo limitado" + "Necessária ação em tempo limitado, tens um minuto para verificares" "Mostrar palavra-passe" "Iniciar chamada" "Sala antiga" @@ -88,6 +90,7 @@ "Ativar" "Fim da sondagem" "Inserir PIN" + "Concluir" "Esqueceu-se da palavra-passe?" "Reencaminhar" "Voltar" @@ -162,10 +165,14 @@ "Atualização disponível" "Sobre" "Política de utilização aceitável" + "Adicionar conta" + "Adicionar outra conta" "A adicionar legenda" "Configurações avançadas" "uma imagem" "Recolha e análise de dados" + "Saíste da sala" + "A tua sessão foi terminada" "Aparência" "Áudio" "Utilizadores bloqueados" @@ -180,6 +187,7 @@ "Convite rejeitado" "Escuro" "Erro de decifragem" + "Descrição" "Opções de programador" "ID do dispositivo" "Conversa direta" @@ -246,7 +254,7 @@ Razão: %1$s." "Permissão" "Afixado" "Por favor, verifica a tua ligação à internet" - "Por favor, aguarde…" + "Por favor, aguarda…" "Tens a certeza que queres concluir esta sondagem?" "Sondagem: %1$s" "Total de votos: %1$s" @@ -289,18 +297,21 @@ Razão: %1$s." "Resultados da pesquisa" "Segurança" "Vista por" + "Selecionar conta" "Enviar para" "A enviar…" "Falha no envio" "Enviada" ". " "Servidor não suportado" + "Servidor indisponível" "URL do servidor" "Configurações" "Localização partilhada" "A terminar sessão" "Algo correu mal" "Encontramos um erro. Por favor, tenta novamente." + "Espaço" "%1$d espaço" "%1$d espaços" @@ -370,6 +381,8 @@ Tens a certeza de que queres continuar?" "O tamanho máximo de ficheiro permitido é: %1$s" "Seleciona a qualidade do vídeo que pretendes carregar." "Seleciona a qualidade de carregamento do vídeo" + "Pesquisar emojis" + "Já tens sessão iniciada como %1$s neste dispositivo." "Seu homeserver precisa ser atualizado para suportar o Matrix Authentication Service e a criação de conta." "Falha ao criar ligação permanente" "%1$s não foi possível carregar o mapa. Por favor, tente novamente mais tarde." @@ -385,7 +398,7 @@ Tens a certeza de que queres continuar?" "Este endereço de sala já existe, tente editar o campo de endereço da sala ou altere o nome da sala" "Alguns caracteres não são permitidos. Apenas letras, dígitos e os seguintes símbolos são suportados! $ & ‘ ( ) * + / ; = ? @ [ ] - . _" "Algumas mensagens não foram enviadas" - "Desculpe, ocorreu um erro" + "Pedimos desculpa, ocorreu um erro desconhecido" "O remetente deste evento não é o dono do dispositivo que o enviou." "A autenticidade desta mensagem cifrada não pode ser garantida neste dispositivo." "Criptografado por um usuário verificado anteriormente." diff --git a/libraries/ui-strings/src/main/res/values-uz/translations.xml b/libraries/ui-strings/src/main/res/values-uz/translations.xml index 80572fd534..4b6bb6a9f5 100644 --- a/libraries/ui-strings/src/main/res/values-uz/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uz/translations.xml @@ -331,6 +331,7 @@ Sababi:%1$s." "Ogohlantirish" "Oʻzgarishlar saqlanmadi. Haqiqatan ham orqaga qaytmoqchimisiz?" "O‘zgartirishlarni saqlaysizmi?" + "Matrix autentifikatsiya xizmati va hisob yaratish imkoniyatini qo‘llab-quvvatlash uchun uy serveringizni yangilash talab etiladi." "Doimiy havola yaratilmadi" "%1$sxaritani yuklay olmadi. Iltimos keyinroq qayta urinib ko\'ring." "Xabarlar yuklanmadi" 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 3b8fb6ae31..951675ce6d 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -40,7 +40,7 @@ "移除表情符号%1$s" "房间头像" "发送文件" - "时限内必须完成的任务" + "限时操作,您有一分钟的时间来验证" "显示密码" "开始通话" "墓碑聊天室" @@ -163,6 +163,8 @@ "有可用升级" "关于" "可接受的使用政策" + "添加账户" + "添加另一个账户" "添加标题" "高级设置" "一张图片" @@ -183,6 +185,7 @@ "邀请已拒绝" "深色" "解密错误" + "描述" "开发者选项" "设备 ID" "私聊" @@ -287,6 +290,7 @@ "搜索结果" "安全" "已读" + "选择账户" "发送至" "正在发送…" "发送失败" @@ -368,6 +372,8 @@ "允许的最大文件大小为:%1$s" "选择您要上传的视频的质量。" "选择视频上传质量" + "搜索表情符号" + "您已在此设备以%1$s 身份登录。" "您的服务器需要升级,以支持 Matrix 鉴权服务和账户创建。" "创建固定链接失败" "%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 49c54a91cd..78d3ca5fdc 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -105,6 +105,7 @@ "Leave" "Leave conversation" "Leave room" + "Leave space" "Load more" "Manage account" "Manage devices" @@ -184,6 +185,7 @@ "Creating room…" "Request canceled" "Left room" + "Left space" "Invite declined" "Dark" "Decryption error" @@ -410,6 +412,9 @@ Are you sure you want to continue?" "Hey, talk to me on %1$s: %2$s" "%1$s Android" "Rageshake to report bug" + "This will also remove you from all rooms in this space." + "This will also remove you from all rooms in this space, including those you’re the only administrator for:" + "Leave %1$s?" "Screenshot" "%1$s: %2$s" "Options" diff --git a/screenshots/de/features.createroom.impl.addpeople_AddPeopleView_Day_3_de.png b/screenshots/de/features.createroom.impl.addpeople_AddPeopleView_Day_3_de.png new file mode 100644 index 0000000000..6a97b76076 --- /dev/null +++ b/screenshots/de/features.createroom.impl.addpeople_AddPeopleView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b105f5a773cfc0d6992a311eeb7edb60faaac10d3747f96d094438e3ce62698 +size 12924 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_0_de.png b/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_0_de.png deleted file mode 100644 index cf3596c54e..0000000000 --- a/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2145d771b6f2634c89877feeefeb0bd2473495e676874186eb492cb163c1a26f -size 14369 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_1_de.png b/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_1_de.png deleted file mode 100644 index f83930a492..0000000000 --- a/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_1_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d070f9a87e3ad6262e1cc8e8010f3af7a7f311710518f1247ca70737f1b86f19 -size 11628 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_2_de.png b/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_2_de.png deleted file mode 100644 index d155bcfe5c..0000000000 --- a/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_2_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d09a459eb74ecda35bebbc01d22325056fca70b68b223d06c13ed817183e33a -size 11720 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_3_de.png b/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_3_de.png deleted file mode 100644 index 07864fae22..0000000000 --- a/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_3_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:669f10bedf9be832c40021e7b06d319433e63ac6d9ae9f635fd83ea57d3cb122 -size 20680 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_4_de.png b/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_4_de.png deleted file mode 100644 index 6a9beadfb3..0000000000 --- a/screenshots/de/features.home.impl.spaces_HomeSpaceItemView_Day_4_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9965b39e2477477d57c9692acaed40cb4574bbf39882ec58046e3e291a5d409b -size 20584 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png index 4b3eeca8e1..0f5f4cf56a 100644 --- a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png +++ b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cba5963ddcd07cc4c68550dc046be6d528003b38086763a4dae07a8ea8cc08e9 -size 126188 +oid sha256:b13217ac65a45328a20c1bbb9ee6acb8f9a64ee85b8101118ae8d5a958a0104f +size 109579 diff --git a/screenshots/de/features.invitepeople.impl_InvitePeopleView_Day_9_de.png b/screenshots/de/features.invitepeople.impl_InvitePeopleView_Day_9_de.png new file mode 100644 index 0000000000..15bfd49357 --- /dev/null +++ b/screenshots/de/features.invitepeople.impl_InvitePeopleView_Day_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8590b5fd61453580add2dc93262f621b1dbefcff45ed9ef1004d0c5606c35dad +size 21730 diff --git a/screenshots/de/features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_de.png b/screenshots/de/features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_de.png new file mode 100644 index 0000000000..949ec34d43 --- /dev/null +++ b/screenshots/de/features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b580adefe5d563c71caaaf17639b84b7e6c8f5eda5c3d154cce9a5176ed7825e +size 24822 diff --git a/screenshots/de/features.space.impl_SpaceView_Day_2_de.png b/screenshots/de/features.space.impl_SpaceView_Day_2_de.png new file mode 100644 index 0000000000..dfbfac62d4 --- /dev/null +++ b/screenshots/de/features.space.impl_SpaceView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c300acd3609d5f5c2b9b641d84dff196c3d44973a270b89f12919dced5b1ff91 +size 47339 diff --git a/screenshots/de/features.space.impl_SpaceView_Day_3_de.png b/screenshots/de/features.space.impl_SpaceView_Day_3_de.png new file mode 100644 index 0000000000..2823c4d3e3 --- /dev/null +++ b/screenshots/de/features.space.impl_SpaceView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c471588072bc12721ae792976ddbbb756206aacd1e2bdfb91f58e79b3f458b1f +size 46103 diff --git a/screenshots/de/libraries.designsystem.components_ProgressDialogWithContent_Day_0_de.png b/screenshots/de/libraries.designsystem.components_ProgressDialogWithContent_Day_0_de.png new file mode 100644 index 0000000000..72dc113ce5 --- /dev/null +++ b/screenshots/de/libraries.designsystem.components_ProgressDialogWithContent_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b110f2913fbdf487b46e92fec76ed372d7f89cab582d1ea9abb3fbaa2cd041f +size 12317 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 9592a58fae..8e59d76a06 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,76 +1,77 @@ // 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",20336,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20343,], ["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_0_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20336,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20336,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20336,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20336,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20336,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20336,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20336,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20336,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20336,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20336,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20336,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20343,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20343,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20343,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20343,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20343,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20343,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20343,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20343,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20343,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20343,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20343,], ["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,], ["features.messages.impl.actionlist_ActionListViewContent_Day_0_en","features.messages.impl.actionlist_ActionListViewContent_Night_0_en",0,], -["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20336,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20336,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20336,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20343,], ["features.messages.impl.actionlist_ActionListViewContent_Day_1_en","features.messages.impl.actionlist_ActionListViewContent_Night_1_en",0,], -["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20336,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20336,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20336,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20336,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20336,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20336,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20336,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20336,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20336,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20336,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20336,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20336,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20336,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20336,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20336,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20336,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20336,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20336,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20336,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20343,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20343,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20343,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20343,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20346,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20343,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20343,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20343,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20343,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20343,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20343,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20343,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20343,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20343,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20336,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20343,], ["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",20336,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20343,], ["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",20336,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20343,], ["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",20336,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20343,], ["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",20336,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20343,], ["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,], @@ -80,19 +81,19 @@ export const screenshots = [ ["libraries.matrix.ui.components_AttachmentThumbnail_Day_6_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_6_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_7_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_7_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_8_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_8_en",0,], -["features.messages.impl.attachments.preview_AttachmentsView_0_en","",20336,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",20336,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",20336,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",20336,], -["features.messages.impl.attachments.preview_AttachmentsView_4_en","",20336,], -["features.messages.impl.attachments.preview_AttachmentsView_5_en","",20336,], -["features.messages.impl.attachments.preview_AttachmentsView_6_en","",20336,], -["features.messages.impl.attachments.preview_AttachmentsView_7_en","",20336,], -["features.messages.impl.attachments.preview_AttachmentsView_8_en","",20336,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",20343,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",20343,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",20343,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",20343,], +["features.messages.impl.attachments.preview_AttachmentsView_4_en","",20343,], +["features.messages.impl.attachments.preview_AttachmentsView_5_en","",20343,], +["features.messages.impl.attachments.preview_AttachmentsView_6_en","",20343,], +["features.messages.impl.attachments.preview_AttachmentsView_7_en","",20343,], +["features.messages.impl.attachments.preview_AttachmentsView_8_en","",20343,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en",0,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en",0,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20336,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20343,], ["libraries.designsystem.components.avatar.internal_AvatarCluster_Avatars_en","",0,], ["libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Day_0_en","libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Night_0_en",0,], ["libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Day_1_en","libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Night_1_en",0,], @@ -224,145 +225,145 @@ export const screenshots = [ ["libraries.designsystem.modifiers_BackgroundVerticalGradientEnterprise_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradientEnterprise_Night_0_en",0,], ["libraries.designsystem.modifiers_BackgroundVerticalGradient_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradient_Night_0_en",0,], ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], -["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20336,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20343,], ["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",20336,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20336,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20336,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20336,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20336,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20336,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20336,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20343,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20343,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20343,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20343,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20343,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20343,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20343,], ["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",20336,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",20336,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",20336,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",20336,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",20336,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",20343,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",20343,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",20343,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",20343,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",20343,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_0_en","features.messages.impl.timeline.components_CallMenuItem_Night_0_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_1_en","features.messages.impl.timeline.components_CallMenuItem_Night_1_en",0,], -["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",20336,], -["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20336,], +["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",20343,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20343,], ["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_5_en","features.messages.impl.timeline.components_CallMenuItem_Night_5_en",0,], ["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,], -["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20336,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20336,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20336,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20336,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20336,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_0_en","features.changeroommemberroles.impl_ChangeRolesView_Night_0_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_10_en","features.changeroommemberroles.impl_ChangeRolesView_Night_10_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_11_en","features.changeroommemberroles.impl_ChangeRolesView_Night_11_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_12_en","features.changeroommemberroles.impl_ChangeRolesView_Night_12_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_1_en","features.changeroommemberroles.impl_ChangeRolesView_Night_1_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_2_en","features.changeroommemberroles.impl_ChangeRolesView_Night_2_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_3_en","features.changeroommemberroles.impl_ChangeRolesView_Night_3_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_4_en","features.changeroommemberroles.impl_ChangeRolesView_Night_4_en",20336,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20343,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20343,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20343,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20343,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20343,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_0_en","features.changeroommemberroles.impl_ChangeRolesView_Night_0_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_10_en","features.changeroommemberroles.impl_ChangeRolesView_Night_10_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_11_en","features.changeroommemberroles.impl_ChangeRolesView_Night_11_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_12_en","features.changeroommemberroles.impl_ChangeRolesView_Night_12_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_1_en","features.changeroommemberroles.impl_ChangeRolesView_Night_1_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_2_en","features.changeroommemberroles.impl_ChangeRolesView_Night_2_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_3_en","features.changeroommemberroles.impl_ChangeRolesView_Night_3_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_4_en","features.changeroommemberroles.impl_ChangeRolesView_Night_4_en",20343,], ["features.changeroommemberroles.impl_ChangeRolesView_Day_5_en","features.changeroommemberroles.impl_ChangeRolesView_Night_5_en",0,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_6_en","features.changeroommemberroles.impl_ChangeRolesView_Night_6_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_7_en","features.changeroommemberroles.impl_ChangeRolesView_Night_7_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_8_en","features.changeroommemberroles.impl_ChangeRolesView_Night_8_en",20336,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_9_en","features.changeroommemberroles.impl_ChangeRolesView_Night_9_en",20336,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",20336,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",20336,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",20336,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",20336,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",20336,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",20336,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",20336,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_6_en","features.changeroommemberroles.impl_ChangeRolesView_Night_6_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_7_en","features.changeroommemberroles.impl_ChangeRolesView_Night_7_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_8_en","features.changeroommemberroles.impl_ChangeRolesView_Night_8_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_9_en","features.changeroommemberroles.impl_ChangeRolesView_Night_9_en",20343,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",20343,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",20343,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",20343,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",20343,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",20343,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",20343,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",20343,], ["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",20336,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20336,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20336,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20336,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20343,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20343,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20343,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20343,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20336,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20343,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20336,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20336,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20336,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20336,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20336,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20336,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20336,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20343,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20343,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20343,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20343,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20343,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20343,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20343,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20336,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20336,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20336,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20343,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20343,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20343,], ["libraries.textcomposer_ComposerModeView_Day_1_en","libraries.textcomposer_ComposerModeView_Night_1_en",0,], ["libraries.textcomposer_ComposerModeView_Day_2_en","libraries.textcomposer_ComposerModeView_Night_2_en",0,], ["libraries.textcomposer_ComposerModeView_Day_3_en","libraries.textcomposer_ComposerModeView_Night_3_en",0,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20336,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20336,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20336,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20336,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20336,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20336,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20343,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20343,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20343,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20343,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20343,], ["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,], ["libraries.designsystem.atomic.atoms_CounterAtom_Day_0_en","libraries.designsystem.atomic.atoms_CounterAtom_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20336,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20336,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20336,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20336,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20336,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20336,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20336,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20336,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20336,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20336,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20336,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20336,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20336,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20336,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20336,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20336,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20336,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20336,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20336,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20336,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20343,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20343,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20343,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20343,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20343,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20343,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20343,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20343,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20343,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20343,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20343,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20343,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20343,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20343,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20343,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20343,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20343,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20343,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20343,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20343,], ["libraries.mediaviewer.impl.gallery.ui_DateItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_DateItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_DateItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_DateItemView_Night_1_en",0,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20336,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20336,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20336,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20336,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20336,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20336,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20336,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20343,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20343,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20343,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20343,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20343,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20343,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20343,], ["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",20336,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20336,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20336,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20343,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20343,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20343,], ["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",20336,], -["features.home.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.home.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",20336,], -["features.home.impl.components_DefaultRoomListTopBar_Day_0_en","features.home.impl.components_DefaultRoomListTopBar_Night_0_en",20336,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20343,], +["features.home.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.home.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",20343,], +["features.home.impl.components_DefaultRoomListTopBar_Day_0_en","features.home.impl.components_DefaultRoomListTopBar_Night_0_en",20343,], ["features.licenses.impl.details_DependenciesDetailsView_Day_0_en","features.licenses.impl.details_DependenciesDetailsView_Night_0_en",0,], -["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20336,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20336,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20336,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20336,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20336,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20336,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20336,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20343,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20343,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20343,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20343,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20343,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20343,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20343,], ["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,], @@ -375,18 +376,18 @@ 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",20336,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20336,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20336,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20336,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20336,], -["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_0_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_0_en",20336,], -["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_1_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_1_en",20336,], -["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_2_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_2_en",20336,], -["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_3_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_3_en",20336,], -["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_4_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_4_en",20336,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20336,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20336,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20343,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20343,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20343,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20343,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20343,], +["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_0_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_0_en",20343,], +["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_1_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_1_en",20343,], +["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_2_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_2_en",20343,], +["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_3_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_3_en",20343,], +["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_4_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_4_en",20343,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20343,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20343,], ["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,], @@ -397,13 +398,13 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20339,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20339,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20343,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20343,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_2_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_2_en",0,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_3_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_3_en",0,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20336,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20336,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20336,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20343,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20343,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20343,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.designsystem.components_ExpandableBottomSheetLayout_en","",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], @@ -422,46 +423,41 @@ 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",20336,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20336,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20336,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20343,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20343,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20343,], ["features.messages.impl.timeline.components_FocusedEventEnterprise_Day_0_en","features.messages.impl.timeline.components_FocusedEventEnterprise_Night_0_en",0,], ["features.messages.impl.timeline.components_FocusedEvent_Day_0_en","features.messages.impl.timeline.components_FocusedEvent_Night_0_en",0,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.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",20336,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20336,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",20343,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20343,], ["libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Night_0_en",0,], ["libraries.designsystem.components.button_GradientFloatingActionButton_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButton_Night_0_en",0,], ["features.messages.impl.timeline.components.group_GroupHeaderView_Day_0_en","features.messages.impl.timeline.components.group_GroupHeaderView_Night_0_en",0,], ["libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Day_0_en","libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Night_0_en",0,], ["libraries.designsystem.atomic.pages_HeaderFooterPage_Day_0_en","libraries.designsystem.atomic.pages_HeaderFooterPage_Night_0_en",0,], -["features.home.impl.spaces_HomeSpaceItemView_Day_0_en","features.home.impl.spaces_HomeSpaceItemView_Night_0_en",20339,], -["features.home.impl.spaces_HomeSpaceItemView_Day_1_en","features.home.impl.spaces_HomeSpaceItemView_Night_1_en",20339,], -["features.home.impl.spaces_HomeSpaceItemView_Day_2_en","features.home.impl.spaces_HomeSpaceItemView_Night_2_en",20339,], -["features.home.impl.spaces_HomeSpaceItemView_Day_3_en","features.home.impl.spaces_HomeSpaceItemView_Night_3_en",20339,], -["features.home.impl.spaces_HomeSpaceItemView_Day_4_en","features.home.impl.spaces_HomeSpaceItemView_Night_4_en",20339,], -["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20339,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20339,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20343,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20343,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20336,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20336,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20343,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20343,], ["features.home.impl_HomeView_Day_11_en","features.home.impl_HomeView_Night_11_en",0,], ["features.home.impl_HomeView_Day_12_en","features.home.impl_HomeView_Night_12_en",0,], -["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20336,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20336,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20336,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20336,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20336,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20336,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20339,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20336,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20336,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20336,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20336,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20336,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20343,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20343,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20343,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20343,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20343,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20343,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20343,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20343,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20343,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20343,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20343,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20343,], ["libraries.designsystem.theme.components_HorizontalDivider_Dividers_en","",0,], ["libraries.designsystem.ruler_HorizontalRuler_Day_0_en","libraries.designsystem.ruler_HorizontalRuler_Night_0_en",0,], ["libraries.designsystem.theme.components_IconButton_Buttons_en","",0,], @@ -480,8 +476,8 @@ export const screenshots = [ ["libraries.designsystem.icons_IconsCompound_Day_5_en","libraries.designsystem.icons_IconsCompound_Night_5_en",0,], ["libraries.designsystem.icons_IconsOther_Day_0_en","libraries.designsystem.icons_IconsOther_Night_0_en",0,], ["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_0_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_0_en",0,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20336,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20336,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20343,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20343,], ["libraries.mediaviewer.impl.gallery.ui_ImageItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_ImageItemView_Night_0_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_0_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_0_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_10_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_10_en",0,], @@ -489,96 +485,97 @@ 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",20336,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20343,], ["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",20336,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20343,], ["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",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20336,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20336,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20343,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20343,], ["features.networkmonitor.api.ui_Indicator_Day_0_en","features.networkmonitor.api.ui_Indicator_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], ["libraries.matrix.ui.media_InitialsAvatarBitmapGenerator_Day_0_en","libraries.matrix.ui.media_InitialsAvatarBitmapGenerator_Night_0_en",0,], -["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20336,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20336,], -["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20336,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20343,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20343,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20343,], ["features.invitepeople.impl_InvitePeopleView_Day_2_en","features.invitepeople.impl_InvitePeopleView_Night_2_en",0,], ["features.invitepeople.impl_InvitePeopleView_Day_3_en","features.invitepeople.impl_InvitePeopleView_Night_3_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20336,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20336,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20336,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20336,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20343,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20343,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20343,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20343,], ["features.invitepeople.impl_InvitePeopleView_Day_8_en","features.invitepeople.impl_InvitePeopleView_Night_8_en",0,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20336,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20336,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20336,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20336,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20336,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20336,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20336,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20346,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20343,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20343,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20343,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20343,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20343,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20343,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20343,], ["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",20336,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20336,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20336,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20336,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20336,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20336,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20336,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20336,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20336,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20336,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20336,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20343,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20343,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20343,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20343,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20343,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20343,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20343,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20343,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20343,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["features.leaveroom.impl_LeaveRoomView_Day_0_en","features.leaveroom.impl_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20336,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20336,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20336,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20336,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20336,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20336,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20336,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20343,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20343,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20343,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20343,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20343,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20343,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20343,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress_Indicators_en","",0,], ["features.messages.impl.link_LinkView_Day_0_en","features.messages.impl.link_LinkView_Night_0_en",0,], -["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20336,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20343,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ListDialog_Day_0_en","libraries.designsystem.components.dialogs_ListDialog_Night_0_en",0,], ["libraries.designsystem.theme.components_ListItemPrimaryActionWithIcon_List_item_-_Primary_action_&_Icon_List_items_en","",0,], @@ -633,36 +630,36 @@ 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",20336,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20336,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20336,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20336,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20343,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20343,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20343,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20343,], ["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",20336,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20336,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20336,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20336,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20336,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20336,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20336,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20336,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20336,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20336,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20336,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20336,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20336,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20336,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20336,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20336,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20336,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20336,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20336,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20336,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20336,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20336,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20336,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20343,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20343,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20343,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20343,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20343,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20343,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20343,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20343,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20343,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20343,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20343,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20343,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20343,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20343,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20343,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20343,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20343,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20343,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20343,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20343,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20343,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20343,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20343,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20336,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20343,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Night_0_en",0,], @@ -675,22 +672,22 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20336,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20336,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20343,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20343,], ["libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en",0,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20336,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20336,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20343,], ["libraries.mediaviewer.impl.local.image_MediaImageView_Day_0_en","libraries.mediaviewer.impl.local.image_MediaImageView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en",0,], @@ -698,14 +695,14 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20336,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20336,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20343,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20343,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20336,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20343,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20336,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20343,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -719,7 +716,7 @@ export const screenshots = [ ["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,], ["libraries.designsystem.theme.components.previews_Menu_Menus_en","",0,], ["features.messages.impl.messagecomposer_MessageComposerViewVoice_Day_0_en","features.messages.impl.messagecomposer_MessageComposerViewVoice_Night_0_en",0,], -["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20336,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20343,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_1_en","features.messages.impl.timeline.components_MessageEventBubble_Night_1_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_2_en","features.messages.impl.timeline.components_MessageEventBubble_Night_2_en",0,], @@ -728,7 +725,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessageEventBubble_Day_5_en","features.messages.impl.timeline.components_MessageEventBubble_Night_5_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_6_en","features.messages.impl.timeline.components_MessageEventBubble_Night_6_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,], -["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20336,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20343,], ["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,], @@ -736,27 +733,27 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_1_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_1_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20336,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20336,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20336,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20336,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20336,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20336,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",20336,], -["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",20336,], -["features.messages.impl_MessagesView_Day_14_en","features.messages.impl_MessagesView_Night_14_en",20336,], -["features.messages.impl_MessagesView_Day_15_en","features.messages.impl_MessagesView_Night_15_en",20336,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20336,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20336,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20336,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20336,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20336,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20336,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20336,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20336,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20336,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20343,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20343,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20343,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20343,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20343,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20343,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",20343,], +["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",20343,], +["features.messages.impl_MessagesView_Day_14_en","features.messages.impl_MessagesView_Night_14_en",20343,], +["features.messages.impl_MessagesView_Day_15_en","features.messages.impl_MessagesView_Night_15_en",20343,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20343,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20343,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20343,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20343,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20343,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20343,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20343,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20343,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20343,], ["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",20336,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20343,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom_Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom_Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -766,109 +763,109 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20336,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20336,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20336,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20343,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20343,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20336,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20336,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20336,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20336,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20336,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20336,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20336,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20343,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20343,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20343,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20343,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20343,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20343,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20343,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], -["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20336,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20343,], ["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_12_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_12_en",0,], ["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_13_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_13_en",0,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20336,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20336,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20343,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonSmall_Buttons_en","",0,], -["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20336,], -["features.changeroommemberroles.impl_PendingMemberRowWithLongName_Day_0_en","features.changeroommemberroles.impl_PendingMemberRowWithLongName_Night_0_en",20336,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20336,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20336,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20336,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20336,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20343,], +["features.changeroommemberroles.impl_PendingMemberRowWithLongName_Day_0_en","features.changeroommemberroles.impl_PendingMemberRowWithLongName_Night_0_en",20343,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20343,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20343,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20343,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20343,], ["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",20336,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20336,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20336,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20343,], ["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20336,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20336,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20336,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20336,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20336,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20336,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20336,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20336,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20336,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20336,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20336,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20336,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20336,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20336,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20343,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20343,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20343,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20343,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20343,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20343,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20343,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20343,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20343,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20343,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20343,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20343,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20343,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20343,], ["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",20336,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20336,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20336,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20336,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20336,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20343,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20343,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20343,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20343,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20343,], ["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",20336,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20336,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20336,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20336,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20336,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20336,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20336,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20336,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20336,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20336,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20336,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20343,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20343,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20343,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20343,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20343,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20343,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20343,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20343,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20343,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20343,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20343,], ["features.poll.api.pollcontent_PollTitleView_Day_0_en","features.poll.api.pollcontent_PollTitleView_Night_0_en",0,], ["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,], @@ -882,203 +879,206 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceRow_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20336,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20336,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20336,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20336,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20343,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20343,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20343,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20343,], ["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","",20336,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20336,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20336,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20336,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20336,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20336,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20336,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20336,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20336,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20336,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20336,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20336,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20336,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20336,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20336,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20336,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20336,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20336,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20336,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20336,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20336,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20336,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20336,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20336,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20336,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20336,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20336,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20343,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20346,], +["libraries.designsystem.components_ProgressDialogWithTextAndContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithTextAndContent_Night_0_en",0,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20343,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20343,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20343,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20343,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20343,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20343,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20343,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20343,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20343,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20343,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20343,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20343,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20343,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20343,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20343,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20343,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20343,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20343,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20343,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20343,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20343,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20343,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20343,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20343,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20343,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20343,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20336,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20336,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20343,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20343,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], ["features.messages.impl.timeline.components.reactionsummary_ReactionSummaryViewContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_ReactionSummaryViewContent_Night_0_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20336,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20336,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20336,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20336,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20336,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20336,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20336,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20343,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20343,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20343,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20343,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20343,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20343,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20343,], ["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",20336,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20336,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20336,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20336,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20336,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20336,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20336,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20336,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20336,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20336,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20336,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20336,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20336,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20336,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20336,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20336,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20336,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20343,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20343,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20343,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20343,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20343,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20343,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20343,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20343,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20343,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20343,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20343,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20343,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20343,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20343,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20343,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20343,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20343,], ["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_0_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_0_en",0,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20336,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20336,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20336,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20336,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",20336,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",20336,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",20336,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",20336,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",20336,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",20336,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",20336,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",20336,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_8_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_8_en",20336,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20343,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20343,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20343,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20343,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",20343,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",20343,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",20343,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",20343,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",20343,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",20343,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",20343,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",20343,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_8_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_8_en",20343,], ["libraries.matrix.ui.room.address_RoomAddressField_Day_0_en","libraries.matrix.ui.room.address_RoomAddressField_Night_0_en",0,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20336,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20336,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20336,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20336,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",20336,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",20336,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",20336,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",20336,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",20336,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",20336,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",20336,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",20336,], -["features.roomdetails.impl_RoomDetails_0_en","",20336,], -["features.roomdetails.impl_RoomDetails_10_en","",20336,], -["features.roomdetails.impl_RoomDetails_11_en","",20336,], -["features.roomdetails.impl_RoomDetails_12_en","",20336,], -["features.roomdetails.impl_RoomDetails_13_en","",20336,], -["features.roomdetails.impl_RoomDetails_14_en","",20336,], -["features.roomdetails.impl_RoomDetails_15_en","",20336,], -["features.roomdetails.impl_RoomDetails_16_en","",20336,], -["features.roomdetails.impl_RoomDetails_17_en","",20336,], -["features.roomdetails.impl_RoomDetails_18_en","",20336,], -["features.roomdetails.impl_RoomDetails_19_en","",20336,], -["features.roomdetails.impl_RoomDetails_1_en","",20336,], -["features.roomdetails.impl_RoomDetails_2_en","",20336,], -["features.roomdetails.impl_RoomDetails_3_en","",20336,], -["features.roomdetails.impl_RoomDetails_4_en","",20336,], -["features.roomdetails.impl_RoomDetails_5_en","",20336,], -["features.roomdetails.impl_RoomDetails_6_en","",20336,], -["features.roomdetails.impl_RoomDetails_7_en","",20336,], -["features.roomdetails.impl_RoomDetails_8_en","",20336,], -["features.roomdetails.impl_RoomDetails_9_en","",20336,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20336,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20336,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20336,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20336,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20336,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20336,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20336,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20336,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20343,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20343,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20343,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20343,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",20343,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",20343,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",20343,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",20343,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",20343,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",20343,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",20343,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",20343,], +["features.roomdetails.impl_RoomDetails_0_en","",20343,], +["features.roomdetails.impl_RoomDetails_10_en","",20343,], +["features.roomdetails.impl_RoomDetails_11_en","",20343,], +["features.roomdetails.impl_RoomDetails_12_en","",20343,], +["features.roomdetails.impl_RoomDetails_13_en","",20343,], +["features.roomdetails.impl_RoomDetails_14_en","",20343,], +["features.roomdetails.impl_RoomDetails_15_en","",20343,], +["features.roomdetails.impl_RoomDetails_16_en","",20343,], +["features.roomdetails.impl_RoomDetails_17_en","",20343,], +["features.roomdetails.impl_RoomDetails_18_en","",20343,], +["features.roomdetails.impl_RoomDetails_19_en","",20343,], +["features.roomdetails.impl_RoomDetails_1_en","",20343,], +["features.roomdetails.impl_RoomDetails_2_en","",20343,], +["features.roomdetails.impl_RoomDetails_3_en","",20343,], +["features.roomdetails.impl_RoomDetails_4_en","",20343,], +["features.roomdetails.impl_RoomDetails_5_en","",20343,], +["features.roomdetails.impl_RoomDetails_6_en","",20343,], +["features.roomdetails.impl_RoomDetails_7_en","",20343,], +["features.roomdetails.impl_RoomDetails_8_en","",20343,], +["features.roomdetails.impl_RoomDetails_9_en","",20343,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20343,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20343,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20343,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20343,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20343,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20343,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20346,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20343,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20343,], ["features.home.impl.components_RoomListContentView_Day_2_en","features.home.impl.components_RoomListContentView_Night_2_en",0,], -["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20336,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20336,], -["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20336,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20336,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20336,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20336,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20336,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20336,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20343,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20343,], +["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20343,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20343,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20343,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20343,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20343,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20343,], ["features.home.impl.search_RoomListSearchContent_Day_0_en","features.home.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20336,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",20336,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",20336,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",20336,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20336,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20336,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20336,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20336,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20336,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20336,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20343,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",20343,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",20343,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",20343,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20343,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20343,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20343,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20343,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20343,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20343,], ["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",20336,], -["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",20336,], -["features.roomdetails.impl.members_RoomMemberListView_Day_9_en","features.roomdetails.impl.members_RoomMemberListView_Night_9_en",20336,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20336,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20336,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20336,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20336,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20336,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20336,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20336,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20336,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20336,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20336,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20336,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20336,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20336,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20336,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20336,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20336,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20336,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20336,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20336,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20336,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20336,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20336,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",20343,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",20343,], +["features.roomdetails.impl.members_RoomMemberListView_Day_9_en","features.roomdetails.impl.members_RoomMemberListView_Night_9_en",20343,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20343,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20343,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20343,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20343,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20343,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20343,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20343,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20343,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20343,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20343,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20343,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20343,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20343,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20343,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20343,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20343,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20343,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20343,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20343,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20343,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20343,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20343,], ["features.home.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.home.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_0_en","features.home.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_10_en","features.home.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -1101,13 +1101,13 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20336,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20336,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20336,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20336,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20336,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20336,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20336,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20343,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20343,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20343,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20343,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20343,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20343,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20343,], ["features.home.impl.components_RoomSummaryRow_Day_3_en","features.home.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_4_en","features.home.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_5_en","features.home.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -1115,80 +1115,80 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_7_en","features.home.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_8_en","features.home.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_9_en","features.home.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20336,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20336,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20336,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20343,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20343,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20343,], ["appicon.enterprise_RoundIcon_en","",0,], ["appicon.element_RoundIcon_en","",0,], ["libraries.designsystem.atomic.atoms_RoundedIconAtom_Day_0_en","libraries.designsystem.atomic.atoms_RoundedIconAtom_Night_0_en",0,], -["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20336,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20336,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20336,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20343,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20343,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20343,], ["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","",20336,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20343,], ["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.startchat.impl.components_SearchMultipleUsersResultItem_en","",20336,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20336,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20336,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20336,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20336,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20336,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20336,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20336,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20336,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20336,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20336,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20336,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_0_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_1_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_2_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_3_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_4_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_5_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_6_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_8_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_0_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_1_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_2_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_3_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_4_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_5_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_6_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_en","",20336,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_8_en","",20336,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20343,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20343,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20343,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20343,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20343,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20343,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20343,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20343,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20343,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20343,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20343,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20343,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_0_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_1_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_2_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_3_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_4_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_5_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_6_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_8_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_0_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_1_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_2_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_3_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_4_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_5_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_6_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_en","",20343,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_8_en","",20343,], ["libraries.designsystem.atomic.atoms_SelectedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_SelectedIndicatorAtom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoomRtl_Day_0_en","libraries.matrix.ui.components_SelectedRoomRtl_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoomRtl_Day_1_en","libraries.matrix.ui.components_SelectedRoomRtl_Night_1_en",0,], @@ -1202,11 +1202,11 @@ export const screenshots = [ ["libraries.matrix.ui.components_SelectedUser_Day_1_en","libraries.matrix.ui.components_SelectedUser_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",20336,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",20336,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",20336,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",20336,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",20336,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",20343,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",20343,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",20343,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",20343,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",20343,], ["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,], @@ -1216,27 +1216,27 @@ export const screenshots = [ ["libraries.matrix.ui.messages.sender_SenderName_Day_6_en","libraries.matrix.ui.messages.sender_SenderName_Night_6_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_7_en","libraries.matrix.ui.messages.sender_SenderName_Night_7_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_8_en","libraries.matrix.ui.messages.sender_SenderName_Night_8_en",0,], -["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20336,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20336,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20336,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20336,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20336,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20336,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20336,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20336,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20343,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20343,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20343,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20343,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20343,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20343,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20343,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20343,], ["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",20336,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20336,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20336,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20336,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20336,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20336,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20336,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20336,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20336,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20336,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20343,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20343,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20343,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20343,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20343,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20343,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20343,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20343,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20343,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20343,], ["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,], @@ -1245,82 +1245,86 @@ 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",20336,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20343,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20339,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20336,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20336,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20343,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20343,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20343,], ["libraries.matrix.ui.components_SpaceMembersViewNoHeroes_Day_0_en","libraries.matrix.ui.components_SpaceMembersViewNoHeroes_Night_0_en",0,], ["libraries.matrix.ui.components_SpaceMembersView_Day_0_en","libraries.matrix.ui.components_SpaceMembersView_Night_0_en",0,], +["features.space.impl_SpaceView_Day_0_en","features.space.impl_SpaceView_Night_0_en",0,], +["features.space.impl_SpaceView_Day_1_en","features.space.impl_SpaceView_Night_1_en",0,], +["features.space.impl_SpaceView_Day_2_en","features.space.impl_SpaceView_Night_2_en",20346,], +["features.space.impl_SpaceView_Day_3_en","features.space.impl_SpaceView_Night_3_en",20346,], ["libraries.designsystem.modifiers_SquareSizeModifierInsideSquare_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], -["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20336,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20336,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20336,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20336,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20336,], -["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20336,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20336,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20343,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20343,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20343,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20343,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20343,], +["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20343,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20343,], ["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",20336,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20343,], ["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",20336,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20343,], ["libraries.designsystem.components.avatar.internal_TextAvatar_Avatars_en","",0,], ["libraries.designsystem.theme.components_TextButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonLarge_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonSmall_Buttons_en","",0,], -["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20336,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20336,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20336,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20336,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20336,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20336,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20336,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20336,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20336,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20336,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20336,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20336,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20336,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20336,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20336,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20343,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20343,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20343,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20343,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20343,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20343,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20343,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20343,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20343,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20343,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20343,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20343,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20343,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20343,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20343,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], -["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20336,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20336,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20343,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20343,], ["libraries.designsystem.components.list_TextFieldListItemEmpty_Text_field_List_item_-_empty_List_items_en","",0,], ["libraries.designsystem.components.list_TextFieldListItemTextFieldValue_Text_field_List_item_-_textfieldvalue_List_items_en","",0,], ["libraries.designsystem.components.list_TextFieldListItem_Text_field_List_item_-_text_List_items_en","",0,], @@ -1332,14 +1336,14 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.txt_TextFileContentView_Day_3_en","libraries.mediaviewer.impl.local.txt_TextFileContentView_Night_3_en",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20336,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20336,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20336,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20343,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20343,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20343,], ["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",20336,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20336,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20343,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20343,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_7_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_7_en",0,], @@ -1349,18 +1353,18 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en",0,], -["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20336,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20343,], ["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",20336,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20336,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20343,], ["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,], @@ -1368,18 +1372,18 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20336,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20336,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20343,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20343,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_6_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20336,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20336,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20336,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20343,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20343,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20343,], ["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",20336,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20336,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20343,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20343,], ["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,], @@ -1388,41 +1392,41 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20336,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20343,], ["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",20336,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20343,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20336,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20343,], ["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","",20336,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20343,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en",0,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20336,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20336,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20343,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20343,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemInformativeView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemInformativeView_Night_0_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20336,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20343,], ["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",20336,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20336,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20336,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20343,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20343,], ["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",20336,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20336,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20343,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20343,], ["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",20336,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20343,], ["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,], @@ -1431,8 +1435,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",20336,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20336,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20343,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20343,], ["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,], @@ -1447,8 +1451,8 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_4_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_5_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20336,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20336,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20343,], ["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,], @@ -1471,85 +1475,85 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_9_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en",0,], -["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20336,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20336,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20343,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20343,], ["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",20336,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20336,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20336,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20336,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20336,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20336,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20336,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20336,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20343,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20343,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20343,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20343,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20343,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20343,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20343,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20343,], ["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",20336,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20343,], ["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",20336,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20343,], ["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",20336,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",20343,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.components.avatar.internal_TombstonedRoomAvatar_Avatars_en","",0,], ["libraries.designsystem.theme.components_TopAppBarStr_App_Bars_en","",0,], ["libraries.designsystem.theme.components_TopAppBar_App_Bars_en","",0,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20336,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20336,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20336,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20336,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20336,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20336,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20336,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20336,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20343,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20343,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20343,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20343,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20343,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20343,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20343,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20343,], ["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",20336,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20336,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20336,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20336,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20336,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20336,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20343,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20343,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20343,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20343,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20343,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20343,], ["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","",20336,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20343,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar.internal_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar.internal_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20336,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20336,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20336,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20336,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20343,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20343,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20343,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20343,], ["features.startchat.impl.components_UserListView_Day_3_en","features.startchat.impl.components_UserListView_Night_3_en",0,], ["features.startchat.impl.components_UserListView_Day_4_en","features.startchat.impl.components_UserListView_Night_4_en",0,], ["features.startchat.impl.components_UserListView_Day_5_en","features.startchat.impl.components_UserListView_Night_5_en",0,], ["features.startchat.impl.components_UserListView_Day_6_en","features.startchat.impl.components_UserListView_Night_6_en",0,], -["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20336,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20343,], ["features.startchat.impl.components_UserListView_Day_8_en","features.startchat.impl.components_UserListView_Night_8_en",0,], -["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20336,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20343,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20336,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20336,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20336,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20336,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20336,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20336,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20336,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20336,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20336,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20336,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20336,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20336,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20343,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20343,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20343,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20343,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20343,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20343,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20343,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20343,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20343,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20343,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20343,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20343,], ["features.verifysession.impl.ui_VerificationUserProfileContent_Day_0_en","features.verifysession.impl.ui_VerificationUserProfileContent_Night_0_en",0,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VideoItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_VideoItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VideoItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_VideoItemView_Night_1_en",0,], -["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20336,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20336,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20343,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20343,], ["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_2_en","features.viewfolder.impl.file_ViewFileView_Night_2_en",0,], -["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20336,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20343,], ["features.viewfolder.impl.file_ViewFileView_Day_4_en","features.viewfolder.impl.file_ViewFileView_Night_4_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_5_en","features.viewfolder.impl.file_ViewFileView_Night_5_en",0,], ["features.viewfolder.impl.folder_ViewFolderView_Day_0_en","features.viewfolder.impl.folder_ViewFolderView_Night_0_en",0,], From b8db02e4acd4b1cc63b66b496b241f7b49c64197 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 15 Sep 2025 11:39:37 +0200 Subject: [PATCH 046/145] Do not center the dialog title text for dialogs with no icon (#5332) * Fix: do not center the dialog title text for dialogs with no icon * Fix alignment for dialogs with icons, add screenshots * Replace text title in previews so the screenshot tests are easier to understand * Update screenshots --------- Co-authored-by: ElementBot --- .../theme/components/AlertDialogContent.kt | 42 ++++++++++++++++++- .../images/appnav.root_RootView_Day_2_en.png | 4 +- .../appnav.root_RootView_Night_2_en.png | 4 +- ...berroles.impl_ChangeRolesView_Day_6_en.png | 4 +- ...rroles.impl_ChangeRolesView_Night_6_en.png | 4 +- ...cline_AcceptDeclineInviteView_Day_3_en.png | 4 +- ...cline_AcceptDeclineInviteView_Day_4_en.png | 4 +- ...cline_AcceptDeclineInviteView_Day_5_en.png | 4 +- ...ine_AcceptDeclineInviteView_Night_3_en.png | 4 +- ...ine_AcceptDeclineInviteView_Night_4_en.png | 4 +- ...ine_AcceptDeclineInviteView_Night_5_en.png | 4 +- ...es.joinroom.impl_JoinRoomView_Day_5_en.png | 4 +- ...es.joinroom.impl_JoinRoomView_Day_8_en.png | 4 +- ....joinroom.impl_JoinRoomView_Night_5_en.png | 4 +- ....joinroom.impl_JoinRoomView_Night_8_en.png | 4 +- ...pl.list_KnockRequestsListView_Day_5_en.png | 4 +- ....list_KnockRequestsListView_Night_5_en.png | 4 +- ....leaveroom.impl_LeaveRoomView_Day_5_en.png | 4 +- ....leaveroom.impl_LeaveRoomView_Day_7_en.png | 4 +- ...eaveroom.impl_LeaveRoomView_Night_5_en.png | 4 +- ...eaveroom.impl_LeaveRoomView_Night_7_en.png | 4 +- ...ttings_LockScreenSettingsView_Day_2_en.png | 4 +- ...ings_LockScreenSettingsView_Night_2_en.png | 4 +- ...n.impl.setup.pin_SetupPinView_Day_3_en.png | 4 +- ...n.impl.setup.pin_SetupPinView_Day_4_en.png | 4 +- ...impl.setup.pin_SetupPinView_Night_3_en.png | 4 +- ...impl.setup.pin_SetupPinView_Night_4_en.png | 4 +- ...changeserver_ChangeServerView_Day_4_en.png | 4 +- ...angeserver_ChangeServerView_Night_4_en.png | 4 +- ...ogin.impl.login_LoginModeView_Day_2_en.png | 4 +- ...in.impl.login_LoginModeView_Night_2_en.png | 4 +- ....impl_AccountDeactivationView_Day_2_en.png | 4 +- ...mpl_AccountDeactivationView_Night_2_en.png | 4 +- ...tachments.preview_AttachmentsView_6_en.png | 4 +- ...d.list_PinnedMessagesListView_Day_0_en.png | 4 +- ...list_PinnedMessagesListView_Night_0_en.png | 4 +- ...ions_NotificationSettingsView_Day_6_en.png | 4 +- ...ions_NotificationSettingsView_Day_7_en.png | 4 +- ...ns_NotificationSettingsView_Night_6_en.png | 4 +- ...ns_NotificationSettingsView_Night_7_en.png | 4 +- ...er.impl_RoomAliasResolverView_Day_1_en.png | 4 +- ...er.impl_RoomAliasResolverView_Day_2_en.png | 4 +- ....impl_RoomAliasResolverView_Night_1_en.png | 4 +- ....impl_RoomAliasResolverView_Night_2_en.png | 4 +- ...ons_ChangeRoomPermissionsView_Day_6_en.png | 4 +- ...s_ChangeRoomPermissionsView_Night_6_en.png | 4 +- ...impl_RoomMemberModerationView_Day_4_en.png | 4 +- ...impl_RoomMemberModerationView_Day_6_en.png | 4 +- ...pl_RoomMemberModerationView_Night_4_en.png | 4 +- ...pl_RoomMemberModerationView_Night_6_en.png | 4 +- ...ureBackupEnterRecoveryKeyView_Day_3_en.png | 4 +- ...eBackupEnterRecoveryKeyView_Night_3_en.png | 4 +- ...et.root_ResetIdentityRootView_Day_1_en.png | 4 +- ....root_ResetIdentityRootView_Night_1_en.png | 4 +- ...p_SecureBackupSetupViewChange_Day_4_en.png | 4 +- ...p_SecureBackupSetupViewChange_Day_5_en.png | 4 +- ...SecureBackupSetupViewChange_Night_4_en.png | 4 +- ...SecureBackupSetupViewChange_Night_5_en.png | 4 +- ...l.setup_SecureBackupSetupView_Day_4_en.png | 4 +- ...l.setup_SecureBackupSetupView_Day_5_en.png | 4 +- ...setup_SecureBackupSetupView_Night_4_en.png | 4 +- ...setup_SecureBackupSetupView_Night_5_en.png | 4 +- ..._a_very_long_title_and_icon_Dialogs_en.png | 3 ++ ...alog_with_a_very_long_title_Dialogs_en.png | 3 ++ ...rmissions.api_PermissionsView_Day_0_en.png | 4 +- ...rmissions.api_PermissionsView_Day_1_en.png | 4 +- ...rmissions.api_PermissionsView_Day_2_en.png | 4 +- ...rmissions.api_PermissionsView_Day_3_en.png | 4 +- ...issions.api_PermissionsView_Night_0_en.png | 4 +- ...issions.api_PermissionsView_Night_1_en.png | 4 +- ...issions.api_PermissionsView_Night_2_en.png | 4 +- ...issions.api_PermissionsView_Night_3_en.png | 4 +- ...nkDialogCreateLinkWithoutText_Day_0_en.png | 4 +- ...DialogCreateLinkWithoutText_Night_0_en.png | 4 +- ...tComposerLinkDialogCreateLink_Day_0_en.png | 4 +- ...omposerLinkDialogCreateLink_Night_0_en.png | 4 +- ...extComposerLinkDialogEditLink_Day_0_en.png | 4 +- ...tComposerLinkDialogEditLink_Night_0_en.png | 4 +- ...es.apperror.impl_AppErrorView_Day_0_en.png | 4 +- ....apperror.impl_AppErrorView_Night_0_en.png | 4 +- 80 files changed, 201 insertions(+), 155 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_DialogWithVeryLongTitleAndIcon_Dialog_with_a_very_long_title_and_icon_Dialogs_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_DialogWithVeryLongTitle_Dialog_with_a_very_long_title_Dialogs_en.png diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/AlertDialogContent.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/AlertDialogContent.kt index 51fe275ee1..7811c26c4a 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/AlertDialogContent.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/AlertDialogContent.kt @@ -142,7 +142,7 @@ internal fun SimpleAlertDialogContent( Text( text = titleText, style = ElementTheme.typography.fontHeadingSmMedium, - textAlign = TextAlign.Center, + textAlign = if (icon != null) TextAlign.Center else TextAlign.Start, ) } }, @@ -510,3 +510,43 @@ internal fun DialogWithThirdButtonPreview() { } } } + +@Preview(group = PreviewGroup.Dialogs, name = "Dialog with a very long title") +@Composable +@Suppress("MaxLineLength") +internal fun DialogWithVeryLongTitlePreview() { + ElementThemedPreview(showBackground = false) { + DialogPreview { + SimpleAlertDialogContent( + title = "Dialog Title that takes more than one line", + content = "A dialog is a type of modal window that appears in front of app content to provide critical information," + + " or prompt for a decision to be made. Learn more", + submitText = "OK", + onSubmitClick = {}, + ) + } + } +} + +@Preview(group = PreviewGroup.Dialogs, name = "Dialog with a very long title and icon") +@Composable +@Suppress("MaxLineLength") +internal fun DialogWithVeryLongTitleAndIconPreview() { + ElementThemedPreview(showBackground = false) { + DialogPreview { + SimpleAlertDialogContent( + icon = { + Icon( + imageVector = CompoundIcons.NotificationsSolid(), + contentDescription = null + ) + }, + title = "Dialog Title that takes more than one line", + content = "A dialog is a type of modal window that appears in front of app content to provide critical information," + + " or prompt for a decision to be made. Learn more", + submitText = "OK", + onSubmitClick = {}, + ) + } + } +} diff --git a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_2_en.png index 3e22d6f5d9..6ed1ff9038 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa7b667e43c0c85a2e4774549d1dbadd5c58049733cc51d9160ad5b245825cd9 -size 21844 +oid sha256:9d27f8fbaed8cdbb6ad03414cf6f8c2d38b3269731ee72f5fe9eab1ad6afe9df +size 21819 diff --git a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_2_en.png index c52172b489..d213d6846f 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:345f0bbff65c752f0bc3295f58befff79cf681d00b0a476e1ea5c9b625b81087 -size 19977 +oid sha256:4227570b201034be916a714dcf27c9ab4d17d6cc3d47a8eab9ffae3b9b61bb4a +size 19967 diff --git a/tests/uitests/src/test/snapshots/images/features.changeroommemberroles.impl_ChangeRolesView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.changeroommemberroles.impl_ChangeRolesView_Day_6_en.png index 4041cbc7ed..af622b1d7a 100644 --- a/tests/uitests/src/test/snapshots/images/features.changeroommemberroles.impl_ChangeRolesView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.changeroommemberroles.impl_ChangeRolesView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:623941550c734147c294ec2294840d9353ac756b054b402b365060602ff614b0 -size 58961 +oid sha256:3c08f5d276bdf222ec98929baa53275e40a76282c9bd15bbf3dce231223ea863 +size 59021 diff --git a/tests/uitests/src/test/snapshots/images/features.changeroommemberroles.impl_ChangeRolesView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.changeroommemberroles.impl_ChangeRolesView_Night_6_en.png index 55506783c0..91bcf2c395 100644 --- a/tests/uitests/src/test/snapshots/images/features.changeroommemberroles.impl_ChangeRolesView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.changeroommemberroles.impl_ChangeRolesView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17ca777cfd4e056078519282f928799dcb2e9aac1ab2757b7cb4cbb1fe93c573 -size 56855 +oid sha256:ded460697c44b23c47534b786d5f259d2ee87bbb6cffb8c6cbd6777bd40090c4 +size 56849 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en.png index 76ec1f565b..c4e9be12cc 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24e40ff9b3ba80d0c00cd6b5a4e29b5b36f0e9ed92e4e6c123f49d88e661fe15 -size 18467 +oid sha256:44c81c89875c5159190cdb40c7d49849eabd8388d54db4bb1f6352b558e79ca0 +size 18626 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en.png index f7cf9ecd24..5474393374 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31fafcdd786b34313af790c5d9111e6f4787bc55587715357f7959b5554149bb -size 19772 +oid sha256:ebf4e51dee36793583638d31128421caee4166e86dd7007a6342729c28e7058c +size 19945 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en.png index 76ec1f565b..c4e9be12cc 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24e40ff9b3ba80d0c00cd6b5a4e29b5b36f0e9ed92e4e6c123f49d88e661fe15 -size 18467 +oid sha256:44c81c89875c5159190cdb40c7d49849eabd8388d54db4bb1f6352b558e79ca0 +size 18626 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en.png index 5d7460384c..bab506a7de 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7346cb947c370f125c23604c39c499a4300334e12d34a8777a9538a2eea2e72d -size 17157 +oid sha256:5825ff69bffd527601323f52f2ba033cb7b9d754b5113d851dd68a0e5c09e45a +size 17308 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en.png index 698b15df00..d0fd29ba04 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81070899b4d7fa3f0620e3d135d85c09746cefa80189ce9a9c8115311c6dd0e3 -size 18293 +oid sha256:06ce5a60d11da9217ba3f70f794df6d51e1c319052bc063f26466c9b9c31e838 +size 18448 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en.png index 5d7460384c..bab506a7de 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7346cb947c370f125c23604c39c499a4300334e12d34a8777a9538a2eea2e72d -size 17157 +oid sha256:5825ff69bffd527601323f52f2ba033cb7b9d754b5113d851dd68a0e5c09e45a +size 17308 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png index 64d8d932d7..5a80c8299e 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c444dbd6815dcb6362b3a595c9a052e81629c09f90cae08cb42f2053ee06d129 -size 27689 +oid sha256:0ae6db46d01c157fcb8bb436b43e38da13723c498a222e68f792ac170ea2e2ac +size 27841 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png index 979b3141be..abf5b32866 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e23c1347af06b2fa6f1982159cdb92b2bed278ab1b4caf782c3916520681d75 -size 26616 +oid sha256:e10c07c74c54920daac28945f2fcafb8956edcd6df5aaac1d7dc757bd119ee3d +size 26750 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png index 7c8b6e4d8a..05ee8fba6c 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4889f91529fddf07ddccb9d1b31f4af4278245d9916694d2197798318fb9469b -size 26163 +oid sha256:9d3a672f30777ff5b487bca938e612de8e34de94dc5ac189659ced73ed49bffa +size 26309 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png index 7c9d79d83e..436ec07c51 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:809913705eb237bdd8575a92be89cf616d27c7d54a32894378f693dbf1969d0a -size 24731 +oid sha256:83b636552b1a28db8bb81e870486acd861ee131f51f8a8980fb3f1471e55ba3f +size 24709 diff --git a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_5_en.png index aa391725b3..22f56c4da8 100644 --- a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c06f9cadc81daeee0925d8684ad70f7f1bf2dac56c30dd4067c223683e5cbde -size 45382 +oid sha256:c6e13b1e5c43efab5cc40daa0118566aea330552075e5409564c496b86db4564 +size 45402 diff --git a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Night_5_en.png index b7b132a64c..4312dcda4b 100644 --- a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b4f3e43f6f01dcf53f27aca683733015781a1b46b9f2db2fa8f3500f5ce802c -size 43246 +oid sha256:d4ae8ce188cf5d380117fef6f98c73285486970267db88b0823409e75fdf1c1b +size 43250 diff --git a/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Day_5_en.png index aa695c8d55..c0d747d0ad 100644 --- a/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e409ac134f70890d14c31fe0939eb73f1aa010915981b344d9466e9c2450b94b -size 31954 +oid sha256:3f5e1530d78162b77a2d8c79142887f28677aba2acaef31c684231202974b3ad +size 31890 diff --git a/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Day_7_en.png index 5a1e48d6a2..f5483d0828 100644 --- a/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a6a89b15219084b3daeec9cbac6304ece498156ead77a003d8043a85660bf2a -size 19286 +oid sha256:ea9f384fe887976aafe2c3f37f077bce21d2234408992a5ea9865594e405a8b8 +size 19451 diff --git a/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Night_5_en.png index e843f51690..ac82f69973 100644 --- a/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a416901c2228c2aee4f8a925bdb87a64dc36ed7727e8897c04205cc4d4147840 -size 30096 +oid sha256:2ec0da2e0489ae016f1cde361aa556ea7b74de12dfa41134fb8306521dd6d14a +size 30137 diff --git a/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Night_7_en.png index 27afcc195a..a90b8327e5 100644 --- a/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.leaveroom.impl_LeaveRoomView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5e028a3770cf87ebdd9d44c012bbad6c409b7edfaccf5607ab5d7a6e6c3194c -size 17713 +oid sha256:40737bdbc9d264e7e1ea43c7c79463f88de844f518f45e0e4c856d78a0e9d6c7 +size 17868 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en.png index 3cc5e9735e..defcb90471 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3d870d023b29f46e356184fc45a2dc6010a088b1b32a690d0d98b43c7bd3eb2 -size 28845 +oid sha256:aa15f390927a533cdff4d42751e19942b0386473301cdb8cd800b37428ca2179 +size 28851 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en.png index ddae20fe60..c2dbf39b83 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4e636767998635b6abb3dbe29af0d42346c7b249125865f5b5a559abffb28ce5 -size 26963 +oid sha256:91251a1871095a734f70d335b3f514d266a5486b1fc57cbd130214f268525f1f +size 26957 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en.png index 035cebd446..085c34f992 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed0200ed72e0d5551e28c90eea2ea3cef40cbcd5fc738839700d42373322ac4b -size 25139 +oid sha256:dbf3b090b0e3b4a00f5ddd86b7b2a62baa62e9cb6d1c24c36191620124dd6d12 +size 25210 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en.png index d66517b825..a50a3c140a 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6411ff6829376d545081c2b66db42e7ce8bafbf72d2809d884f81a56864e0aab -size 29732 +oid sha256:53187c4901a528f5ea59fff3def64197eb0664ebffe85f48635c5cf1720c977a +size 29700 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en.png index 7b92e39b10..78f23cecd5 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f5fb7a9c99700b05fe90af1ae17428202e4a2d4c0e5c1f246825160e3a42b15 -size 23148 +oid sha256:5a430db03a543cf4517f9086e3bdf43cae72ac544f5fa1b5994bf62aa3151463 +size 23228 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en.png index 727473d6a6..ca9ce8c967 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e90c76587699c68a30a788ed8fdacfa7a53f49e7bfeea0c7a2809d5b4b5e662 -size 27622 +oid sha256:0870a37c29bd5b62b559e47c0eb2dfd7ae94ed38efd62d3fa91eb0d646923373 +size 27565 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_4_en.png index dcfebea1ec..4b0e30affb 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:41280716b1e864b904e073171ab0f3aaec6fdc8917481259924db581196fd1ed -size 26115 +oid sha256:50002e3a2f804fd2be0953fdb751ca73582a542346e0b854e256264e4f3ab77f +size 26047 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_4_en.png index 8984aa75d5..a0af69b135 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d52037a99c6094a488c3fe097a83a01b9de75c43ac3ead61f0c1e451783bbcf7 -size 24912 +oid sha256:48469fbca8f0b6c4c1fae05db27c1117ce6284bd6167a5f27dc06dd7d3c02a19 +size 24862 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Day_2_en.png index 8f1e86273e..e448af41a9 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65bffac39daeea85b38ef1379cb3ec35bbe5bf0a230dd5b66f342a58c12d6e0a -size 25701 +oid sha256:bc0fb8588ecf00b34d52da98594ee1aa841eef98cf5825fbea535e1fa871a2ef +size 25646 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Night_2_en.png index 0a32ebc655..4aa9046ed9 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20263696842e1790bae3bcbceb6268f9d960de48e1a32b2459ab5abeaf5d20d6 -size 24506 +oid sha256:0c60a197c679eda6323efacad6a33acc6f0175ebd0af7928609313c2189d6b9a +size 24455 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_2_en.png index 8dfb060ca6..0314ca1c8f 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2ecb0a9f48a2c43c700dab7b21497d5bebdb63ad87a63d15525f596374b6748 -size 61650 +oid sha256:d81131943b6ff08a8c52827e956a9cf8d830b8523c192e645b116733aff2f8e5 +size 61663 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_2_en.png index ba552634c9..7b590a03ac 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cbb1c1dc96055d4fe6aa792363abc00fb72bd8af758b9e8597f45725a983111d -size 57951 +oid sha256:5204b189cf02f8f0145427df1c412e597cea106bcb87ac259b28e41ba55f2f0c +size 58053 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_6_en.png index 8cb89ad06b..41a7341afa 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9368b86a0b2c5f73e97837019327e2f3c7898ded80de259a7c03e58f2ccf2b64 -size 72852 +oid sha256:a4214287ce64b1083c0be5227fd6e16066f3932c48ce7a8953d47999a5924fbf +size 72848 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en.png index 8d0c6973de..345ce9fe34 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4559bcfab614255a51b2f73869d5ffc91fbc9fa53ef61c2ae02bd28c88bd838 -size 20773 +oid sha256:1d194ea0d68d15d8950277eb747047b7ac3c809eecfc12877296b7eb67d67b02 +size 20707 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en.png index 760ee954e9..25a06027ed 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29c5b7ad11fdc97564ce4be236f3b89785029ed65d75be23ba97f5267438739d -size 18932 +oid sha256:4dc9805c2f2d910491da944f1cf91430bcc5a8a91137eaaf301f65955d0d350e +size 18798 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_6_en.png index 43bcd29a9b..d79f995fa3 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3028295864a6990944ec3485d8b7c1aa1688005f34b7519e66176c6d945aff2c -size 39907 +oid sha256:a049311411b2e8bb777d2fefc74c06e943c36931e24419c1b9155472643a6f90 +size 39868 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_7_en.png index 4ea3d6f1fe..ab1af1559f 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3ae8baf10cc1adb8bb3dbf4bfcd2653876dd9c902b07d33bd4f5690d18ec263 -size 44378 +oid sha256:f6a577b1e7047237c485fbcf49d238478f638e471e5f637721c7766eacc89799 +size 44275 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_6_en.png index 83bfb6b921..b515219e5c 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8c02eaac714aff002eb259579a33e576fabd4442c2c4528df36ef5c910a9efb -size 37262 +oid sha256:5d1b3e8eabbbd4ebfb3dd14e67aa0944d7d291688d458423c4bb45c47056c028 +size 37280 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_7_en.png index a6c7b2d4d7..0c6d1d86c3 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0637ff1ee39762445cc8c5498680152c2e2e8012108231fcc2974326a1d8cdb7 -size 41466 +oid sha256:ff548b1c9c9d4fc8b376ae12be6c8468483715726bc0deecf4fc4f5854d727ad +size 41418 diff --git a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en.png index 979b3141be..abf5b32866 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e23c1347af06b2fa6f1982159cdb92b2bed278ab1b4caf782c3916520681d75 -size 26616 +oid sha256:e10c07c74c54920daac28945f2fcafb8956edcd6df5aaac1d7dc757bd119ee3d +size 26750 diff --git a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en.png index b8f30f125d..282404ccf8 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9de3402e8b3eed6005f80ecaeea325c533a0f4d51e2dd306baf6ad97a09042d4 -size 23373 +oid sha256:78826ac37783b67bab2ef7c93a5ad1fcc1fd167926ed3e6d8c92eb826c8b603f +size 23462 diff --git a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en.png index 7c9d79d83e..436ec07c51 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:809913705eb237bdd8575a92be89cf616d27c7d54a32894378f693dbf1969d0a -size 24731 +oid sha256:83b636552b1a28db8bb81e870486acd861ee131f51f8a8980fb3f1471e55ba3f +size 24709 diff --git a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en.png index 6d2ed82c26..2751f65665 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d1f5a7d25ad07bc6b0025ea4f600609f58b881452e826d93378f80062626b3d7 -size 21274 +oid sha256:7114651af7b2d0ae7caf7df0bb81bb117fc829bd9795a57e173729673c23d231 +size 21082 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en.png index ac4547d7ea..e2f67353d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8747685a776c4fc59d8fed90b057ab18b8abf2670cd430ca4afcf745a402724 -size 44114 +oid sha256:146e40d680e33105cc06cda3a113432f29b42bf7f3b539b4ea17fd6ff9a9265e +size 44093 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en.png index ce722d74ff..f6dad027b0 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a775ed56c60c2a57cdd8b2d4c54cf557919be0b80948a50402445c37806fd319 -size 42168 +oid sha256:49f72fe1ede6eb11c2e1572af27086df4f9c7eec45cf3ea3cfe6235ea89f12cf +size 42150 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en.png index 93944ff960..edec0550ca 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7065059b0ee8165b631225f5468fd937c217b08544ec38bdb13d46dd0bda8a24 -size 30646 +oid sha256:e4063555b9c55be91104f51d5696383aba383d2b7b8d6ff490058f0228e45f81 +size 30659 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en.png index 77921fc181..14d1396ac9 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2071ff6a7820d23d20cfd6863b9cfa05439f596f9a94c734806d807d661bb813 -size 29383 +oid sha256:c09808dc63bad05bc97a6d5d5f62a4d0fd3db86c17e4662aa2b56eb50143361a +size 29415 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en.png index 2d0471e281..9c6513bfd1 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:517ee043e2f70702df7791d8b352598a6d7ff572ab5c7d42c606597b3efe2c35 -size 28815 +oid sha256:3a7da5666d690d5d9a6be61225b169e4703626ebc15f2f8f4f3e98d2e322de39 +size 28831 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en.png index b067bdbc8c..9f70cf870f 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77d65977a990b8505d61bc61d39ea6855e5e931cb0503a380464df9eee4f5854 -size 27528 +oid sha256:97d7e385717dd0ebd7beac1fbd5c205e13f7785febabee15bfffa0026b8d530c +size 27616 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en.png index ecae8555cf..30a1a4772b 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4582d19a955cf012c6c07db728b69ae4a1e99dff7292f1dcaaf68d8afbe3141 -size 34821 +oid sha256:4cea381806f7903d56640938ccf8c6d3312c8d27cd768629209db4f8a4b2fb75 +size 34891 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en.png index 705fe313f0..f661545528 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1f6f4d016188b72e28ae192c9b2379a0734e34586295e4ab5a522fabb152f58 -size 32356 +oid sha256:8a8e1b4d80a8144e92f047259047104c39e3e03ddb9f49ce8b643f5ee074b772 +size 32384 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 26c609c792..e999349e08 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:74ff9446fb276504638707c4779e3947147d40c9114ee126ad22d1977b5d5397 -size 54561 +oid sha256:1b50f2f588c835adb9d2025fd904e8cd9462fb5b5f6952249b3b1fc0098e7dd2 +size 54688 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 f095c5ecda..790641766b 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:2ffd2de03c34e9329cdb7320b67133e5e9f66e3cb133c3be2cb2101de3a789dc -size 52502 +oid sha256:2584a9ff1ae31f50e2c7902e2a04995c7c96d8085328e262d50be8a2395f71f9 +size 52541 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en.png index 6b6971c495..b7b6ca3318 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e631c4ab7338e9c5fff80de7b5981a85d495b47977d10318a6d02c381d6049e -size 48632 +oid sha256:0a8cf71b7c7ac794bf6f0fd71fe477cb0dd651ff86ad649fe4eaa9e8df83b1cf +size 48594 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en.png index 23adbc3c79..0d260a0a24 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0091ef6aaa0eb66f155e13993d6979578ea27464d28397af9b7587fbc715942 -size 35688 +oid sha256:098b7a3b50e1bca8c03c55c8b118694339b6cc9033f4f94847c66a59e0629743 +size 35835 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en.png index 32fab22a28..8e3198caa9 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7bba3b6776ec442d113b8cade307624406f608b09ca2dddad1ce07a35259d664 -size 45896 +oid sha256:a31fc85a97482f83147f8db4b3dc95ac5c96d16fbcc849ab44588bc2462377d7 +size 45963 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en.png index 6b69fa0ceb..e1c6673840 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d1091a682fa4b15d85e557a5681b502da7c9c13de54090125b5256d976ef7322 -size 32707 +oid sha256:01d4b4598591373cbb507fd4074aafc7a0c04d84bf89ff1bc7e4eaa7bde71a7a +size 32880 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en.png index 6b6971c495..b7b6ca3318 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e631c4ab7338e9c5fff80de7b5981a85d495b47977d10318a6d02c381d6049e -size 48632 +oid sha256:0a8cf71b7c7ac794bf6f0fd71fe477cb0dd651ff86ad649fe4eaa9e8df83b1cf +size 48594 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en.png index 78b88b0ef7..da055ab499 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a2502351e4de7541a573b2d5b0f51643ea90dcad1c654acbcb342660df5fc98 -size 34306 +oid sha256:f4317eb9258f74756d4ecf3aa430dad3ee93cf446588d6fac9bbc6cc12c2c3b0 +size 34467 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en.png index 32fab22a28..8e3198caa9 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7bba3b6776ec442d113b8cade307624406f608b09ca2dddad1ce07a35259d664 -size 45896 +oid sha256:a31fc85a97482f83147f8db4b3dc95ac5c96d16fbcc849ab44588bc2462377d7 +size 45963 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en.png index 4c2d58030a..b556abffc7 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f8a48e08a9caf55dffd4812091f24c26995dcb238944cd409c93c0ef359cebb -size 31493 +oid sha256:d233d12ec3b268a3b0f4b902a784708dc4ddbf804b37d72111c5b7677e346ade +size 31620 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_DialogWithVeryLongTitleAndIcon_Dialog_with_a_very_long_title_and_icon_Dialogs_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_DialogWithVeryLongTitleAndIcon_Dialog_with_a_very_long_title_and_icon_Dialogs_en.png new file mode 100644 index 0000000000..460e856f24 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_DialogWithVeryLongTitleAndIcon_Dialog_with_a_very_long_title_and_icon_Dialogs_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b77f17f245a60b74cfff9e28cb0f5d0251172332582e00f6bcf2767c867bcd8 +size 56167 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_DialogWithVeryLongTitle_Dialog_with_a_very_long_title_Dialogs_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_DialogWithVeryLongTitle_Dialog_with_a_very_long_title_Dialogs_en.png new file mode 100644 index 0000000000..f4a7fb3f40 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_DialogWithVeryLongTitle_Dialog_with_a_very_long_title_Dialogs_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1a1350f33dd50756aa7aa175e1dbcc42c5922d82d4b020a5556c4e0d1db0b83 +size 63540 diff --git a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_0_en.png index fb72370351..9e034f4fbb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa702b884d741412232c68245a503bd06c9fa595be214a5cf852ea576d77a031 -size 26878 +oid sha256:db93be255fb6e9a70e1814bad2275b4e828924aaf5dfdf623456290d986926e4 +size 26853 diff --git a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_1_en.png index 56fabcb8dd..e8c4accaa2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e70d3bca33fcccf6839b651a8b34056bdcbbacf18447fa8d99638ddc0558816 -size 26011 +oid sha256:ba7cfc134e5843e053b6c0c842b882e4a18505451959510da2b02dc295f68da6 +size 25985 diff --git a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_2_en.png index c138569904..e4163ee256 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdb77ac0053690361d44a221b2290557a8c9b904eb5771c0d4bc76382804d579 -size 26491 +oid sha256:cf678d8b087d3d1ae5ee836ec177828610ad074ff611c8b7f42b4008589bd911 +size 26467 diff --git a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_3_en.png index b1232891b4..32f9d544c8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3de92534cdb971ef27901f9e5e5db4146b39d9527afc6b23daa7718ee4d4ef4 -size 20477 +oid sha256:0dd34239f647ab049a3dc1bf137abd7e31081b4da25fa850ee9ebff89a84cdd4 +size 20460 diff --git a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_0_en.png index a839d4cbc7..b10e2188fe 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:541193db62ebb995d81e48f3f49a74fafa8d537e9dd99c4f7537b7cd14a1258f -size 25632 +oid sha256:bad56fc6d29cf54e760ac8a5d13e53cc047651c2cf1efad36d78dc3956bb7ac5 +size 25638 diff --git a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_1_en.png index d995dccd06..f0a44c0dbc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ae7e0666a300169a5eabf6e8d8e8846034488e3cfb92e5c2fe7c1cdd889fb13 -size 24880 +oid sha256:42dd21b3fcd9faf803153852e6ed3ea9d43cdc6f637af3d1a34f4892174738eb +size 24886 diff --git a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_2_en.png index d3b91b8c05..f8337097c9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a32d7138ef227596fda8a0e495143ab255bf30913ce62d1d9f40108cde79728 -size 25303 +oid sha256:4284ff47ebb1fec51df90fc55219f9354c751d3d9c17c2b2d133b57550176b7b +size 25304 diff --git a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_3_en.png index 9951f9bfa8..fafa6d94da 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.permissions.api_PermissionsView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c91ae52ece27098b46e8e787407262d50bbf95c42550b26faeabcc8a382887eb -size 19192 +oid sha256:952550c4bfcc10751a781279f1023b11e42e73b585c97543a212e3d7f0887218 +size 19156 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en.png index 3d5088afdc..b50f6ba4a8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:736b3ea3821b421acc7f1a9bdc54f2c603dea34f3995150cccaef8b15ba7d75f -size 13057 +oid sha256:bda5872074c486c4b40575b814ed2865056c02931ee1ca0f8a98ac4f32e5f985 +size 13093 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en.png index 411f8fb2da..00b7d45027 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a56cab67985d64487d89b4ccecff21e391c1562edebb28280ee5ab8f26393ad -size 12033 +oid sha256:648ac4cf6333a39bbfb90e8a5faf2aa44a1de19c1613bf754ca6bc4d1974fc8b +size 12019 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en.png index 7713f10b20..639d4d89b5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:886722a012510c51dbad9a50f717d6ba3b64425cad0755c90afdd84a5cae67c0 -size 14618 +oid sha256:7f6e0912e5970104f0dd09d152d6a3da57f7a2b2201aa5dd86c7b691c797edad +size 14637 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en.png index 426d15e371..24e9093c2e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:edc8ef6512ea5f0e39a059d692063455e2e1174a8e781eccd0c2e543d156544a -size 13465 +oid sha256:b879de5d6db9a3cff7de4b2ee779b6c8de456b629f31f07fcb57de3a7c7e7c28 +size 13409 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en.png index 560c64ad73..0342d06c2c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ab5214a9d6f424910cd551454392443faf40694b5c3bde3b839fc49e1cd0633 -size 16845 +oid sha256:14d318ad147102d2cdfe73c46125fa35864010ea38dcd6dfbb7fd3b12d64d878 +size 16873 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en.png index 6a2334efc0..262699e09c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7bd2c66d3efa336b22df0820ea9e36633a22b36927163d3950088d9179376dd -size 15521 +oid sha256:2ce99713434fba303745a45b2d12d18841c90ab65fb650e700a5fc9e070bd79f +size 15496 diff --git a/tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Day_0_en.png index 08d3f6a214..d15340871f 100644 --- a/tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f181687fc541a13928a35f9a23fca99a6d6bdf7875bd900fe444d001b5256fd -size 19592 +oid sha256:94242ace02e2db7156e0bdb2c3e071255006ed839360db7a3322a8bb0a93458a +size 19570 diff --git a/tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Night_0_en.png index 38a6de5b59..616d21a8a6 100644 --- a/tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81f5b10dd42b27de179693857fd3aeac838562540371be8e789801c69755edc6 -size 18202 +oid sha256:b7ff1f5db38fc99452f0a7c3fc727ee7ffd6461b69ad0d58d126571b1eea2851 +size 18191 From d9e7d74d2d2c8c2358be30d62fe866964f6b78e5 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 15 Sep 2025 15:15:10 +0200 Subject: [PATCH 047/145] Upgrade Rust SDK bindings to v25.09.15 (#5353) * Upgrade Rust SDK bindings to `v25.09.15`: This contains important changes to the APIs used to build the EC widget. * Use the new `intent` parameter correctly, by calculating locally its behaviour based on whether the room is a DM and there is an ongoing call or not. Using just the `intent` parameter is our end goal, but sadly this is not fully supported by the current EC embedded `v0.15.0`, so we need to add a workaround using the `skipLobby` and `preload` parameters. --- .../impl/utils/DefaultCallWidgetProvider.kt | 10 +++++-- .../messages/impl/MessagesPresenterTest.kt | 10 ++++--- gradle/libs.versions.toml | 2 +- .../libraries/matrix/api/timeline/Timeline.kt | 2 +- .../api/widget/CallWidgetSettingsProvider.kt | 1 + .../matrix/impl/timeline/RustTimeline.kt | 2 +- .../DefaultCallWidgetSettingsProvider.kt | 27 +++++++++---------- .../matrix/test/timeline/FakeTimeline.kt | 4 +-- .../widget/FakeCallWidgetSettingsProvider.kt | 12 ++++++--- 9 files changed, 43 insertions(+), 27 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt index 77d98d12af..dc217bc118 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt @@ -45,8 +45,14 @@ class DefaultCallWidgetProvider( val customBaseUrl = appPreferencesStore.getCustomElementCallBaseUrlFlow().firstOrNull() val baseUrl = customBaseUrl ?: EMBEDDED_CALL_WIDGET_BASE_URL - val isEncrypted = room.info().isEncrypted ?: room.getUpdatedIsEncrypted().getOrThrow() - val widgetSettings = callWidgetSettingsProvider.provide(baseUrl, encrypted = isEncrypted, direct = room.isDm()) + val roomInfo = room.info() + val isEncrypted = roomInfo.isEncrypted ?: room.getUpdatedIsEncrypted().getOrThrow() + val widgetSettings = callWidgetSettingsProvider.provide( + baseUrl = baseUrl, + encrypted = isEncrypted, + direct = room.isDm(), + hasActiveCall = roomInfo.hasRoomCall, + ) val callUrl = room.generateWidgetWebViewUrl( widgetSettings = widgetSettings, clientId = clientId, 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 6a1abd4b3f..122dd021a4 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 @@ -160,9 +160,9 @@ class MessagesPresenterTest { @Test fun `present - handle toggling a reaction`() = runTest { val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true) - val toggleReactionSuccess = lambdaRecorder { _: String, _: EventOrTransactionId -> Result.success(Unit) } + val toggleReactionSuccess = lambdaRecorder { _: String, _: EventOrTransactionId -> Result.success(true) } val toggleReactionFailure = - lambdaRecorder { _: String, _: EventOrTransactionId -> Result.failure(IllegalStateException("Failed to send reaction")) } + lambdaRecorder { _: String, _: EventOrTransactionId -> Result.failure(IllegalStateException("Failed to send reaction")) } val timeline = FakeTimeline().apply { this.toggleReactionLambda = toggleReactionSuccess @@ -200,7 +200,11 @@ class MessagesPresenterTest { @Test fun `present - handle toggling a reaction twice`() = runTest { val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true) - val toggleReactionSuccess = lambdaRecorder { _: String, _: EventOrTransactionId -> Result.success(Unit) } + var toggle = false + val toggleReactionSuccess = lambdaRecorder { _: String, _: EventOrTransactionId -> + toggle = !toggle + Result.success(toggle) + } val timeline = FakeTimeline().apply { this.toggleReactionLambda = toggleReactionSuccess diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ca2f436f54..9c0ec6c01b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -176,7 +176,7 @@ jsoup = "org.jsoup:jsoup:1.21.2" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.1.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.10" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.15" 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/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 4eceeac4da..f8f5793368 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 @@ -151,7 +151,7 @@ interface Timeline : AutoCloseable { suspend fun redactEvent(eventOrTransactionId: EventOrTransactionId, reason: String?): Result - suspend fun toggleReaction(emoji: String, eventOrTransactionId: EventOrTransactionId): Result + suspend fun toggleReaction(emoji: String, eventOrTransactionId: EventOrTransactionId): Result suspend fun forwardEvent(eventId: EventId, roomIds: List): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt index 7a735bbf92..8334fb5fde 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt @@ -15,5 +15,6 @@ interface CallWidgetSettingsProvider { widgetId: String = UUID.randomUUID().toString(), encrypted: Boolean, direct: Boolean, + hasActiveCall: Boolean, ): MatrixWidgetSettings } 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 97d9ef68c1..b4888dafe0 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 @@ -431,7 +431,7 @@ class RustTimeline( } } - override suspend fun toggleReaction(emoji: String, eventOrTransactionId: EventOrTransactionId): Result = withContext(dispatcher) { + override suspend fun toggleReaction(emoji: String, eventOrTransactionId: EventOrTransactionId): Result = withContext(dispatcher) { runCatchingExceptions { inner.toggleReaction( key = emoji, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt index f656cc16a4..00947f99a2 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt @@ -18,9 +18,8 @@ import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings import io.element.android.services.analytics.api.AnalyticsService import kotlinx.coroutines.flow.first import org.matrix.rustcomponents.sdk.newVirtualElementCallWidget +import timber.log.Timber import uniffi.matrix_sdk.EncryptionSystem -import uniffi.matrix_sdk.HeaderStyle -import uniffi.matrix_sdk.NotificationType import uniffi.matrix_sdk.VirtualElementCallWidgetConfig import uniffi.matrix_sdk.VirtualElementCallWidgetProperties import uniffi.matrix_sdk.Intent as CallIntent @@ -32,7 +31,7 @@ class DefaultCallWidgetSettingsProvider( private val callAnalyticsCredentialsProvider: CallAnalyticCredentialsProvider, private val analyticsService: AnalyticsService, ) : CallWidgetSettingsProvider { - override suspend fun provide(baseUrl: String, widgetId: String, encrypted: Boolean, direct: Boolean): MatrixWidgetSettings { + override suspend fun provide(baseUrl: String, widgetId: String, encrypted: Boolean, direct: Boolean, hasActiveCall: Boolean): MatrixWidgetSettings { val isAnalyticsEnabled = analyticsService.userConsentFlow.first() val properties = VirtualElementCallWidgetProperties( elementCallUrl = baseUrl, @@ -49,18 +48,18 @@ class DefaultCallWidgetSettingsProvider( parentUrl = null, ) val config = VirtualElementCallWidgetConfig( - preload = null, - appPrompt = false, - confineToRoom = true, - // TODO We probably want to provide different values for this field. - intent = CallIntent.START_CALL, - hideScreensharing = false, - // For backwards compatibility, it'll be ignored in recent versions of Element Call - hideHeader = true, - controlledAudioDevices = true, - header = HeaderStyle.APP_BAR, - sendNotificationType = if (direct) NotificationType.RING else NotificationType.NOTIFICATION, + // TODO remove this once we have the next EC version + preload = false, + // TODO remove this once we have the next EC version skipLobby = null, + intent = when { + direct && hasActiveCall -> CallIntent.JOIN_EXISTING_DM + hasActiveCall -> CallIntent.JOIN_EXISTING + direct -> CallIntent.START_CALL_DM + else -> CallIntent.START_CALL + }.also { + Timber.d("Starting/joining call with intent: $it") + } ) val rustWidgetSettings = newVirtualElementCallWidget( props = properties, 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 42a0ecbcb6..6ebd9f9f50 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 @@ -304,9 +304,9 @@ class FakeTimeline( ) } - var toggleReactionLambda: (emoji: String, eventOrTransactionId: EventOrTransactionId) -> Result = { _, _ -> lambdaError() } + var toggleReactionLambda: (emoji: String, eventOrTransactionId: EventOrTransactionId) -> Result = { _, _ -> lambdaError() } - override suspend fun toggleReaction(emoji: String, eventOrTransactionId: EventOrTransactionId): Result = simulateLongTask { + override suspend fun toggleReaction(emoji: String, eventOrTransactionId: EventOrTransactionId): Result = simulateLongTask { toggleReactionLambda( emoji, eventOrTransactionId, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt index d052a3d9b8..6caa6e1570 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt @@ -11,12 +11,18 @@ import io.element.android.libraries.matrix.api.widget.CallWidgetSettingsProvider import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings class FakeCallWidgetSettingsProvider( - private val provideFn: (String, String, Boolean, Boolean) -> MatrixWidgetSettings = { _, _, _, _ -> MatrixWidgetSettings("id", true, "url") } + private val provideFn: (String, String, Boolean, Boolean, Boolean) -> MatrixWidgetSettings = { _, _, _, _, _ -> MatrixWidgetSettings("id", true, "url") } ) : CallWidgetSettingsProvider { val providedBaseUrls = mutableListOf() - override suspend fun provide(baseUrl: String, widgetId: String, encrypted: Boolean, direct: Boolean): MatrixWidgetSettings { + override suspend fun provide( + baseUrl: String, + widgetId: String, + encrypted: Boolean, + direct: Boolean, + hasActiveCall: Boolean + ): MatrixWidgetSettings { providedBaseUrls += baseUrl - return provideFn(baseUrl, widgetId, encrypted, direct) + return provideFn(baseUrl, widgetId, encrypted, direct, hasActiveCall) } } From 9f59db81672437ad6a2c8401dc506babd532dfa1 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 15 Sep 2025 16:00:13 +0200 Subject: [PATCH 048/145] Media viewer: release the `ExoPlayers` when the hosting composables are disposed (#5351) * Media viewer: release the `ExoPlayers` when the hosting composables are disposed * Restore missing `removeListener` call --- .../impl/local/video/MediaVideoView.kt | 107 +++++++++++------- 1 file changed, 69 insertions(+), 38 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt index 8e826383b6..0ce19aaa84 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt @@ -10,12 +10,14 @@ package io.element.android.libraries.mediaviewer.impl.local.video import android.annotation.SuppressLint import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.widget.FrameLayout +import androidx.annotation.OptIn import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -33,6 +35,7 @@ import androidx.media3.common.MediaItem import androidx.media3.common.Player import androidx.media3.common.Player.STATE_READY import androidx.media3.common.Timeline +import androidx.media3.common.util.UnstableApi import androidx.media3.exoplayer.ExoPlayer import androidx.media3.ui.AspectRatioFrameLayout import androidx.media3.ui.PlayerView @@ -55,6 +58,7 @@ import io.element.android.libraries.mediaviewer.impl.local.player.togglePlay import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState import kotlinx.coroutines.delay import me.saket.telephoto.zoomable.zoomable +import timber.log.Timber import kotlin.time.Duration.Companion.seconds @SuppressLint("UnsafeOptInUsageError") @@ -165,35 +169,6 @@ private fun ExoPlayerMediaVideoView( } } - LaunchedEffect(exoPlayer.isPlaying) { - if (exoPlayer.isPlaying) { - while (true) { - mediaPlayerControllerState = mediaPlayerControllerState.copy( - progressInMillis = exoPlayer.currentPosition, - ) - delay(200) - } - } else { - // Ensure we render the final state - mediaPlayerControllerState = mediaPlayerControllerState.copy( - progressInMillis = exoPlayer.currentPosition, - ) - } - } - - var needsAutoPlay by remember { mutableStateOf(autoplay) } - - LaunchedEffect(needsAutoPlay, isDisplayed, mediaPlayerControllerState.isReady) { - val isReadyAndNotPlaying = mediaPlayerControllerState.isReady && !mediaPlayerControllerState.isPlaying - if (needsAutoPlay && isDisplayed && isReadyAndNotPlaying) { - // When displayed, start autoplaying - exoPlayer.play() - needsAutoPlay = false - } else if (!isDisplayed && mediaPlayerControllerState.isPlaying) { - // If not displayed, make sure to pause the video - exoPlayer.pause() - } - } if (localMedia?.uri != null) { LaunchedEffect(localMedia.uri) { val mediaItem = MediaItem.fromUri(localMedia.uri) @@ -263,16 +238,72 @@ private fun ExoPlayerMediaVideoView( ) } - OnLifecycleEvent { _, event -> - when (event) { - Lifecycle.Event.ON_CREATE -> exoPlayer.addListener(playerListener) - Lifecycle.Event.ON_RESUME -> exoPlayer.prepare() - Lifecycle.Event.ON_PAUSE -> exoPlayer.pause() - Lifecycle.Event.ON_DESTROY -> { - exoPlayer.release() - exoPlayer.removeListener(playerListener) + LaunchedEffect(exoPlayer.isPlaying) { + if (exoPlayer.isPlaying) { + while (true) { + mediaPlayerControllerState = mediaPlayerControllerState.copy( + progressInMillis = exoPlayer.currentPosition, + ) + delay(200) } - else -> Unit + } else { + // Ensure we render the final state + mediaPlayerControllerState = mediaPlayerControllerState.copy( + progressInMillis = exoPlayer.currentPosition, + ) + } + } + + ExoPlayerLifecycleHelper( + exoPlayer = exoPlayer, + autoplay = autoplay, + isDisplayed = isDisplayed, + playerListener = playerListener, + mediaPlayerControllerState = mediaPlayerControllerState, + ) +} + +@OptIn(UnstableApi::class) +@Composable +private fun ExoPlayerLifecycleHelper( + exoPlayer: ExoPlayer, + autoplay: Boolean, + isDisplayed: Boolean, + playerListener: Player.Listener, + mediaPlayerControllerState: MediaPlayerControllerState, +) { + // Prepare and release the exoPlayer with the composable lifecycle + DisposableEffect(Unit) { + Timber.d("ExoPlayerMediaVideoView DisposableEffect: initializing exoPlayer") + exoPlayer.addListener(playerListener) + exoPlayer.prepare() + + onDispose { + Timber.d("Disposing exoplayer") + if (!exoPlayer.isReleased) { + exoPlayer.removeListener(playerListener) + exoPlayer.release() + } + } + } + + var needsAutoPlay by remember { mutableStateOf(autoplay) } + LaunchedEffect(needsAutoPlay, isDisplayed, mediaPlayerControllerState.isReady) { + val isReadyAndNotPlaying = mediaPlayerControllerState.isReady && !mediaPlayerControllerState.isPlaying + if (needsAutoPlay && isDisplayed && isReadyAndNotPlaying) { + // When displayed, start autoplaying + exoPlayer.play() + needsAutoPlay = false + } else if (!isDisplayed && mediaPlayerControllerState.isPlaying) { + // If not displayed, make sure to pause the video + exoPlayer.pause() + } + } + + // Pause playback when lifecycle is paused + OnLifecycleEvent { _, event -> + if (event == Lifecycle.Event.ON_PAUSE && exoPlayer.isPlaying) { + exoPlayer.pause() } } } From e79281a78a5766e683b3d95ee194a809da9441b2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 15 Sep 2025 16:26:54 +0200 Subject: [PATCH 049/145] feature (space) : start logic for joining space --- .../android/features/invite/api/InviteData.kt | 9 + .../joinroom/impl/JoinRoomPresenter.kt | 185 ++++++++++++------ .../features/joinroom/impl/JoinRoomState.kt | 10 +- .../joinroom/impl/JoinRoomStateProvider.kt | 12 +- .../joinroom/impl/JoinRoomPresenterTest.kt | 2 +- .../features/space/impl/SpacePresenter.kt | 6 +- .../matrix/api/spaces/SpaceRoomList.kt | 3 +- .../matrix/impl/spaces/RustSpaceRoomList.kt | 4 +- .../matrix/impl/spaces/SpaceRoomCache.kt | 6 +- .../matrix/impl/spaces/SpaceRoomCacheTest.kt | 4 +- .../matrix/test/spaces/FakeSpaceRoomList.kt | 7 +- 11 files changed, 167 insertions(+), 81 deletions(-) diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt index eb1dfd3df6..fa296edc1c 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt @@ -12,6 +12,7 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo +import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.parcelize.Parcelize @Parcelize @@ -36,3 +37,11 @@ fun RoomInfo.toInviteData(): InviteData { isDm = isDm, ) } + +fun SpaceRoom.toInviteData(): InviteData { + return InviteData( + roomId = roomId, + roomName = name ?: roomId.value, + isDm = false, + ) +} 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 5fe12a42d9..c8a107eba4 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 @@ -23,6 +23,7 @@ import androidx.compose.runtime.setValue import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.Inject import im.vector.app.features.analytics.plan.JoinedRoom +import io.element.android.features.invite.api.InviteData import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteEvents import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteState @@ -41,18 +42,23 @@ import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.matrix.api.exception.ErrorKind import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.room.NotJoinedRoom import io.element.android.libraries.matrix.api.room.RoomInfo -import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.RoomMembershipDetails import io.element.android.libraries.matrix.api.room.RoomType import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo +import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.ui.model.toInviteSender import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import java.util.Optional +import kotlin.jvm.optionals.getOrNull @Inject class JoinRoomPresenter( @@ -80,6 +86,8 @@ class JoinRoomPresenter( ): JoinRoomPresenter } + private val spaceList = matrixClient.spaceService.spaceRoomList(roomId) + @Composable override fun present(): JoinRoomState { val coroutineScope = rememberCoroutineScope() @@ -87,6 +95,9 @@ class JoinRoomPresenter( val roomInfo by remember { matrixClient.getRoomInfoFlow(roomId) }.collectAsState(initial = Optional.empty()) + val spaceRoom by remember { + spaceList.currentSpaceFlow() + }.collectAsState() val joinAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } val knockAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } val cancelKnockAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } @@ -96,55 +107,41 @@ class JoinRoomPresenter( val hideInviteAvatars by matrixClient.rememberHideInvitesAvatar() val canReportRoom by produceState(false) { value = matrixClient.canReportRoom() } - val contentState by produceState( - initialValue = ContentState.Loading, - key1 = roomInfo, - key2 = retryCount, - key3 = isDismissingContent, - ) { + var contentState by remember { + mutableStateOf(ContentState.Loading) + } + LaunchedEffect(roomInfo, retryCount, isDismissingContent, spaceRoom) { when { - isDismissingContent -> value = ContentState.Dismissing + isDismissingContent -> contentState = ContentState.Dismissing roomInfo.isPresent -> { val notJoinedRoom = matrixClient.getRoomPreview(roomIdOrAlias, serverNames).getOrNull() - val (sender, reason) = when (roomInfo.get().currentUserMembership) { - CurrentUserMembership.BANNED -> { - // Workaround to get info about the sender for banned rooms - // TODO re-do this once we have a better API in the SDK - val membershipDetails = notJoinedRoom?.membershipDetails()?.getOrNull() - membershipDetails?.senderMember to membershipDetails?.currentUserMember?.membershipChangeReason - } - CurrentUserMembership.INVITED -> { - roomInfo.get().inviter to null - } - else -> null to null - } + val membershipDetails = notJoinedRoom?.membershipDetails()?.getOrNull() val joinedMembersCountOverride = notJoinedRoom?.previewInfo?.numberOfJoinedMembers - value = roomInfo.get().toContentState( - membershipSender = sender, + contentState = roomInfo.get().toContentState( joinedMembersCountOverride = joinedMembersCountOverride, - reason = reason, + membershipDetails = membershipDetails, + childrenCount = spaceRoom.getOrNull()?.childrenCount, ) } + spaceRoom.isPresent -> { + val spaceRoom = spaceRoom.get() + // Only use this state when space is not locally known + contentState = if (spaceRoom.state != null) { + ContentState.Loading + } else { + spaceRoom.toContentState() + } + } roomDescription.isPresent -> { - value = roomDescription.get().toContentState() + contentState = roomDescription.get().toContentState() } else -> { - value = ContentState.Loading + contentState = ContentState.Loading val result = matrixClient.getRoomPreview(roomIdOrAlias, serverNames) - value = result.fold( + contentState = result.fold( onSuccess = { preview -> - val membershipInfo = when (preview.previewInfo.membership) { - CurrentUserMembership.INVITED, - CurrentUserMembership.BANNED, - CurrentUserMembership.KNOCKED -> { - preview.membershipDetails().getOrNull() - } - else -> null - } - preview.previewInfo.toContentState( - senderMember = membershipInfo?.senderMember, - reason = membershipInfo?.currentUserMember?.membershipChangeReason, - ) + val membershipDetails = preview.membershipDetails().getOrNull() + preview.previewInfo.toContentState(membershipDetails) }, onFailure = { throwable -> if (throwable is ClientException.MatrixApi && (throwable.kind == ErrorKind.NotFound || throwable.kind == ErrorKind.Forbidden)) { @@ -223,6 +220,15 @@ class JoinRoomPresenter( } } + private suspend fun getRoomPreviewIfKnown(membership: CurrentUserMembership?): NotJoinedRoom? { + return when (membership) { + CurrentUserMembership.INVITED, + CurrentUserMembership.KNOCKED, + CurrentUserMembership.BANNED -> matrixClient.getRoomPreview(roomIdOrAlias, serverNames).getOrNull() + else -> null + } + } + private fun CoroutineScope.knockRoom(knockAction: MutableState>, message: String) = launch { knockAction.runUpdatingState { knockRoom(roomIdOrAlias, message, serverNames) @@ -252,7 +258,7 @@ class JoinRoomPresenter( } } -private fun RoomPreviewInfo.toContentState(senderMember: RoomMember?, reason: String?): ContentState { +private fun RoomPreviewInfo.toContentState(membershipDetails: RoomMembershipDetails?): ContentState { return ContentState.Loaded( roomId = roomId, name = name, @@ -262,17 +268,37 @@ private fun RoomPreviewInfo.toContentState(senderMember: RoomMember?, reason: St isDm = false, roomType = roomType, roomAvatarUrl = avatarUrl, - joinAuthorisationStatus = when (membership) { - CurrentUserMembership.INVITED -> { - JoinAuthorisationStatus.IsInvited( - inviteData = toInviteData(), - inviteSender = senderMember?.toInviteSender() - ) - } - CurrentUserMembership.BANNED -> JoinAuthorisationStatus.IsBanned(senderMember?.toInviteSender(), reason) - CurrentUserMembership.KNOCKED -> JoinAuthorisationStatus.IsKnocked - else -> joinRule.toJoinAuthorisationStatus() - } + joinAuthorisationStatus = computeJoinAuthorisationStatus( + membership, + membershipDetails, + joinRule, + { toInviteData() } + ), + joinRule = joinRule, + childrenCount = null, + heroes = persistentListOf(), + ) +} + +private fun SpaceRoom.toContentState(): ContentState { + return ContentState.Loaded( + roomId = roomId, + name = name, + topic = topic, + alias = canonicalAlias, + numberOfMembers = numJoinedMembers.toLong(), + isDm = false, + roomType = roomType, + roomAvatarUrl = avatarUrl, + joinAuthorisationStatus = computeJoinAuthorisationStatus( + membership = state, + membershipDetails = null, + joinRule = joinRule, + inviteData = { toInviteData() } + ), + childrenCount = childrenCount, + joinRule = joinRule, + heroes = heroes.toPersistentList(), ) } @@ -291,15 +317,25 @@ internal fun RoomDescription.toContentState(): ContentState { RoomDescription.JoinRule.KNOCK -> JoinAuthorisationStatus.CanKnock RoomDescription.JoinRule.PUBLIC -> JoinAuthorisationStatus.CanJoin else -> JoinAuthorisationStatus.Unknown - } + }, + childrenCount = null, + joinRule = when (joinRule) { + RoomDescription.JoinRule.KNOCK -> JoinRule.Knock + RoomDescription.JoinRule.PUBLIC -> JoinRule.Public + RoomDescription.JoinRule.RESTRICTED -> JoinRule.Restricted(persistentListOf()) + RoomDescription.JoinRule.KNOCK_RESTRICTED -> JoinRule.KnockRestricted(persistentListOf()) + RoomDescription.JoinRule.INVITE -> JoinRule.Invite + RoomDescription.JoinRule.UNKNOWN -> null + }, + heroes = persistentListOf() ) } @VisibleForTesting internal fun RoomInfo.toContentState( - membershipSender: RoomMember?, joinedMembersCountOverride: Long?, - reason: String?, + membershipDetails: RoomMembershipDetails?, + childrenCount: Int?, ): ContentState { return ContentState.Loaded( roomId = id, @@ -310,21 +346,40 @@ internal fun RoomInfo.toContentState( isDm = isDm, roomType = if (isSpace) RoomType.Space else RoomType.Room, roomAvatarUrl = avatarUrl, - joinAuthorisationStatus = when (currentUserMembership) { - CurrentUserMembership.INVITED -> JoinAuthorisationStatus.IsInvited( - inviteData = toInviteData(), - inviteSender = membershipSender?.toInviteSender(), - ) - CurrentUserMembership.BANNED -> JoinAuthorisationStatus.IsBanned( - banSender = membershipSender?.toInviteSender(), - reason = reason, - ) - CurrentUserMembership.KNOCKED -> JoinAuthorisationStatus.IsKnocked - else -> joinRule.toJoinAuthorisationStatus() - } + joinAuthorisationStatus = computeJoinAuthorisationStatus( + membership = currentUserMembership, + membershipDetails = membershipDetails, + joinRule = joinRule, + inviteData = { toInviteData() } + ), + joinRule = joinRule, + childrenCount = childrenCount, + heroes = heroes ) } +private fun computeJoinAuthorisationStatus( + membership: CurrentUserMembership?, + membershipDetails: RoomMembershipDetails?, + joinRule: JoinRule?, + inviteData: () -> InviteData, +): JoinAuthorisationStatus { + return when (membership) { + CurrentUserMembership.INVITED -> { + JoinAuthorisationStatus.IsInvited( + inviteData = inviteData(), + inviteSender = membershipDetails?.senderMember?.toInviteSender() + ) + } + CurrentUserMembership.BANNED -> JoinAuthorisationStatus.IsBanned( + membershipDetails?.senderMember?.toInviteSender(), + membershipDetails?.membershipChangeReason + ) + CurrentUserMembership.KNOCKED -> JoinAuthorisationStatus.IsKnocked + else -> joinRule.toJoinAuthorisationStatus() + } +} + private fun JoinRule?.toJoinAuthorisationStatus(): JoinAuthorisationStatus { return when (this) { JoinRule.Knock, 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 5b9f8007a3..36a74c813e 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -18,7 +18,10 @@ 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.RoomType import io.element.android.libraries.matrix.api.room.join.JoinRoom +import io.element.android.libraries.matrix.api.room.join.JoinRule +import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.model.InviteSender +import kotlinx.collections.immutable.ImmutableList internal const val MAX_KNOCK_MESSAGE_LENGTH = 500 @@ -41,9 +44,6 @@ data class JoinRoomState( val joinAuthorisationStatus = when (contentState) { is ContentState.Loaded -> { when { - contentState.roomType == RoomType.Space -> { - JoinAuthorisationStatus.IsSpace(applicationName) - } isJoinActionUnauthorized -> { JoinAuthorisationStatus.Unauthorized } @@ -81,8 +81,12 @@ sealed interface ContentState { val roomType: RoomType, val roomAvatarUrl: String?, val joinAuthorisationStatus: JoinAuthorisationStatus, + val joinRule: JoinRule?, + val childrenCount: Int?, + val heroes: ImmutableList, ) : ContentState { val showMemberCount = numberOfMembers != null + val isSpace = roomType is RoomType.Space fun avatarData(size: AvatarSize): AvatarData { return AvatarData( diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 8f891fe645..244cc0579d 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -22,7 +22,10 @@ import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.matrix.api.room.RoomType import io.element.android.libraries.matrix.api.room.join.JoinRoom +import io.element.android.libraries.matrix.api.room.join.JoinRule +import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.model.InviteSender +import kotlinx.collections.immutable.toPersistentList open class JoinRoomStateProvider : PreviewParameterProvider { override val values: Sequence @@ -78,6 +81,7 @@ open class JoinRoomStateProvider : PreviewParameterProvider { alias = null, topic = "This is the topic of a space", roomType = RoomType.Space, + childrenCount = 42, ) ), aJoinRoomState( @@ -160,6 +164,9 @@ fun aLoadedContentState( roomType: RoomType = RoomType.Room, roomAvatarUrl: String? = null, joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown, + childrenCount: Int? = null, + joinRule : JoinRule? = null, + heroes: List = emptyList() ) = ContentState.Loaded( roomId = roomId, name = name, @@ -169,7 +176,10 @@ fun aLoadedContentState( isDm = isDm, roomType = roomType, roomAvatarUrl = roomAvatarUrl, - joinAuthorisationStatus = joinAuthorisationStatus + joinAuthorisationStatus = joinAuthorisationStatus, + childrenCount = childrenCount, + joinRule = joinRule, + heroes = heroes.toPersistentList() ) fun aJoinRoomState( 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 cabab56802..5a6631146d 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 @@ -964,7 +964,7 @@ class JoinRoomPresenterTest { presenter.test { skipItems(1) awaitItem().also { state -> - assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.IsSpace("AppName")) + assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.UnsupportedSpace("AppName")) } } } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt index 95597371a6..3b07e06051 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt @@ -29,6 +29,8 @@ import kotlinx.collections.immutable.toPersistentSet import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import java.util.Optional +import kotlin.jvm.optionals.getOrNull @Inject class SpacePresenter( @@ -64,7 +66,7 @@ class SpacePresenter( } }.collectAsState() - val currentSpace by remember { spaceRoomList.currentSpaceFlow() }.collectAsState(null) + val currentSpace by remember { spaceRoomList.currentSpaceFlow() }.collectAsState(Optional.empty()) fun handleEvents(event: SpaceEvents) { when (event) { @@ -72,7 +74,7 @@ class SpacePresenter( } } return SpaceState( - currentSpace = currentSpace, + currentSpace = currentSpace.getOrNull(), children = children.toPersistentList(), seenSpaceInvites = seenSpaceInvites, hideInvitesAvatar = hideInvitesAvatar, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt index a591fc2537..e55e1b87bd 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoomList.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.api.spaces import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow +import java.util.Optional interface SpaceRoomList { sealed interface PaginationStatus { @@ -16,7 +17,7 @@ interface SpaceRoomList { data class Idle(val hasMoreToLoad: Boolean) : PaginationStatus } - fun currentSpaceFlow(): Flow + fun currentSpaceFlow(): StateFlow> val spaceRoomsFlow: Flow> val paginationStatusFlow: StateFlow diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt index e3f2132a2f..7e6a9f6afa 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt @@ -16,10 +16,12 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState +import java.util.Optional import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList class RustSpaceRoomList( @@ -31,7 +33,7 @@ class RustSpaceRoomList( ) : SpaceRoomList { private val inner = CompletableDeferred() - override fun currentSpaceFlow(): Flow { + override fun currentSpaceFlow(): StateFlow> { return spaceRoomCache.getSpaceRoomFlow(roomId) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt index 8b7d1f5e1b..f9d45e5ea6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt @@ -12,7 +12,9 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update +import java.util.Optional /** * An in memory cache of space rooms. @@ -20,8 +22,8 @@ import kotlinx.coroutines.flow.update */ class SpaceRoomCache { private val inMemoryCache = MutableStateFlow>(emptyMap()) - fun getSpaceRoomFlow(roomId: RoomId): Flow { - return inMemoryCache.mapState { it[roomId] } + fun getSpaceRoomFlow(roomId: RoomId): StateFlow> { + return inMemoryCache.mapState { Optional.ofNullable(it[roomId]) } } fun update(spaceRooms: List) { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt index 0679ce1a33..061169c5e8 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCacheTest.kt @@ -21,7 +21,7 @@ class SpaceRoomCacheTest { fun `getSpaceRoomFlow emits items`() = runTest { val sut = SpaceRoomCache() sut.getSpaceRoomFlow(A_ROOM_ID).test { - assertThat(awaitItem()).isNull() + assertThat(awaitItem().isEmpty).isTrue() val room = aSpaceRoom( roomId = A_ROOM_ID, roomType = RoomType.Room, @@ -34,7 +34,7 @@ class SpaceRoomCacheTest { roomType = RoomType.Space, ) sut.update(listOf(space)) - assertThat(awaitItem()).isEqualTo(space) + assertThat(awaitItem().get()).isEqualTo(space) val spaceOther = aSpaceRoom( roomId = A_ROOM_ID_2, roomType = RoomType.Space, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt index eb71f33fa2..ca424eac11 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/spaces/FakeSpaceRoomList.kt @@ -15,6 +15,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import java.util.Optional class FakeSpaceRoomList( initialSpaceFlowValue: SpaceRoom? = null, @@ -22,11 +23,11 @@ class FakeSpaceRoomList( initialSpaceRoomList: SpaceRoomList.PaginationStatus = SpaceRoomList.PaginationStatus.Loading, private val paginateResult: () -> Result = { lambdaError() }, ) : SpaceRoomList { - private val _currentSpaceFlow: MutableStateFlow = MutableStateFlow(initialSpaceFlowValue) - override fun currentSpaceFlow(): Flow = _currentSpaceFlow.asStateFlow() + private val _currentSpaceFlow: MutableStateFlow> = MutableStateFlow(Optional.ofNullable(initialSpaceFlowValue)) + override fun currentSpaceFlow() = _currentSpaceFlow.asStateFlow() fun emitCurrentSpace(value: SpaceRoom?) { - _currentSpaceFlow.value = value + _currentSpaceFlow.value = Optional.ofNullable(value) } private val _spaceRoomsFlow: MutableStateFlow> = MutableStateFlow(initialSpaceRoomsValue) From 2571bbf4bad948f8b0349eb2265b0cf8395af508 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 09:57:21 +0200 Subject: [PATCH 050/145] Remove unused NavTarget.Empty --- .../android/features/messages/impl/MessagesFlowNode.kt | 7 ------- 1 file changed, 7 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 2f563395f7..5cbce99701 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 @@ -15,7 +15,6 @@ import androidx.lifecycle.lifecycleScope import com.bumble.appyx.core.lifecycle.subscribe import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node -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 @@ -126,9 +125,6 @@ class MessagesFlowNode( plugins = plugins ) { sealed interface NavTarget : Parcelable { - @Parcelize - data object Empty : NavTarget - @Parcelize data class Messages(val focusedEventId: EventId?) : NavTarget @@ -399,9 +395,6 @@ class MessagesFlowNode( } createNode(buildContext, plugins = listOf(callback)) } - NavTarget.Empty -> { - node(buildContext) {} - } NavTarget.KnockRequestsList -> { knockRequestsListEntryPoint.createNode(this, buildContext) } From 8fa7f71d0d9ab39b31d611d8a4d016987cd53e91 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 09:58:42 +0200 Subject: [PATCH 051/145] Let SpaceEntryPoint.Inputs implement NodeInputs. --- .../io/element/android/features/space/api/SpaceEntryPoint.kt | 3 ++- .../kotlin/io/element/android/features/space/impl/SpaceNode.kt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt index 88cbbad5dd..5f7be8dba0 100644 --- a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt +++ b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt @@ -11,6 +11,7 @@ import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import io.element.android.libraries.architecture.FeatureEntryPoint +import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.matrix.api.core.RoomId interface SpaceEntryPoint : FeatureEntryPoint { @@ -27,7 +28,7 @@ interface SpaceEntryPoint : FeatureEntryPoint { data class Inputs( val roomId: RoomId - ) : Plugin + ) : NodeInputs interface Callback : Plugin { fun onOpenRoom(roomId: RoomId) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt index d37be4c76c..a4828fe9fe 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceNode.kt @@ -16,6 +16,7 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.Inject import io.element.android.annotations.ContributesNode import io.element.android.features.space.api.SpaceEntryPoint +import io.element.android.libraries.architecture.inputs import io.element.android.libraries.di.SessionScope @ContributesNode(SessionScope::class) @@ -25,7 +26,7 @@ class SpaceNode( @Assisted plugins: List, presenterFactory: SpacePresenter.Factory, ) : Node(buildContext, plugins = plugins) { - private val inputs = plugins.filterIsInstance().single() + private val inputs: SpaceEntryPoint.Inputs = inputs() private val callback = plugins.filterIsInstance().single() private val presenter = presenterFactory.create(inputs) From 9ac74af722919fb44c47fbae5e22786fd2d70b44 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 10:06:16 +0200 Subject: [PATCH 052/145] Small cleanup --- .../permissions/ChangeRoomPermissionsNode.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/permissions/ChangeRoomPermissionsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/permissions/ChangeRoomPermissionsNode.kt index 2a3e5a2bad..906c97fb2e 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/permissions/ChangeRoomPermissionsNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/permissions/ChangeRoomPermissionsNode.kt @@ -34,10 +34,7 @@ class ChangeRoomPermissionsNode( ) : NodeInputs, Parcelable private val inputs: Inputs = inputs() - - private val presenter = presenterFactory.run { - create(inputs.section) - } + private val presenter = presenterFactory.create(inputs.section) @Composable override fun View(modifier: Modifier) { From a3b160aacee890b23e57bcfa614c09176f94dbeb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 10:08:50 +0200 Subject: [PATCH 053/145] Small cleanup --- .../impl/ChangeRolesNode.kt | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNode.kt b/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNode.kt index 342fba632f..26b1af6bbb 100644 --- a/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNode.kt +++ b/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNode.kt @@ -37,16 +37,7 @@ class ChangeRolesNode( ) : NodeInputs private val inputs: Inputs = inputs() - - private val presenter = presenterFactory.run { - val role = when (inputs.listType) { - ChangeRoomMemberRolesListType.Admins -> RoomMember.Role.Admin - ChangeRoomMemberRolesListType.Moderators -> RoomMember.Role.Moderator - ChangeRoomMemberRolesListType.SelectNewOwnersWhenLeaving -> RoomMember.Role.Owner(isCreator = false) - } - create(role) - } - + private val presenter = presenterFactory.create(inputs.listType.toRoomMemberRole()) private val stateFlow = launchMolecule { presenter.present() } suspend fun waitForRoleChanged() { @@ -63,3 +54,9 @@ class ChangeRolesNode( ) } } + +private fun ChangeRoomMemberRolesListType.toRoomMemberRole() = when (this) { + ChangeRoomMemberRolesListType.Admins -> RoomMember.Role.Admin + ChangeRoomMemberRolesListType.Moderators -> RoomMember.Role.Moderator + ChangeRoomMemberRolesListType.SelectNewOwnersWhenLeaving -> RoomMember.Role.Owner(isCreator = false) +} From 7a60e46d8f1f6f30ce075dbba5a9bcfd4c793b94 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 10:24:16 +0200 Subject: [PATCH 054/145] Method can be private. --- .../io/element/android/features/home/impl/HomeFlowNode.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt index a8eeb6eee8..d8ecf7016f 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt @@ -164,7 +164,7 @@ class HomeFlowNode( stateFlow.value.roomListState.eventSink(RoomListEvents.LeaveRoom(roomId, needsConfirmation = false)) } - fun rootNode(buildContext: BuildContext): Node { + private fun rootNode(buildContext: BuildContext): Node { return node(buildContext) { modifier -> val state by stateFlow.collectAsState() val activity = requireNotNull(LocalActivity.current) From d6acd94deea4eee41be32aa58b272433150bea2e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 10:33:18 +0200 Subject: [PATCH 055/145] Simplify code --- .../impl/ChangeRoomMemberRolesRootNode.kt | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRoomMemberRolesRootNode.kt b/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRoomMemberRolesRootNode.kt index 0ce019aa16..5055761e6e 100644 --- a/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRoomMemberRolesRootNode.kt +++ b/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRoomMemberRolesRootNode.kt @@ -39,16 +39,13 @@ class ChangeRoomMemberRolesRootNode( roomComponentFactory: RoomComponentFactory, ) : ParentNode( navModel = PermanentNavModel( - navTargets = setOf(NavTarget.Root), + navTargets = setOf(NavTarget), savedStateMap = buildContext.savedStateMap, ), buildContext = buildContext, plugins = plugins, ), DependencyInjectionGraphOwner, ChangeRoomMemberRolesEntryPoint.NodeProxy { - sealed interface NavTarget : Parcelable { - @Parcelize - object Root : NavTarget - } + @Parcelize object NavTarget : Parcelable data class Inputs( val joinedRoom: JoinedRoom, @@ -60,14 +57,10 @@ class ChangeRoomMemberRolesRootNode( override val graph = roomComponentFactory.create(inputs.joinedRoom) override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { - return when (navTarget) { - NavTarget.Root -> { - createNode( - buildContext = buildContext, - plugins = listOf(ChangeRolesNode.Inputs(listType = inputs.listType)), - ) - } - } + return createNode( + buildContext = buildContext, + plugins = listOf(ChangeRolesNode.Inputs(listType = inputs.listType)), + ) } @Composable From 0955866dcdd9a75526e0a76fd4aceaf754492f66 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 10:36:35 +0200 Subject: [PATCH 056/145] Rename to follow naming convention --- .../features/viewfolder/impl/DefaultViewFolderEntryPoint.kt | 6 +++--- .../root/{ViewFolderRootNode.kt => ViewFolderFlowNode.kt} | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) rename features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/root/{ViewFolderRootNode.kt => ViewFolderFlowNode.kt} (98%) diff --git a/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPoint.kt b/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPoint.kt index 64d469c34f..330ca68a8c 100644 --- a/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPoint.kt +++ b/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPoint.kt @@ -14,7 +14,7 @@ import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Inject import io.element.android.features.viewfolder.api.ViewFolderEntryPoint -import io.element.android.features.viewfolder.impl.root.ViewFolderRootNode +import io.element.android.features.viewfolder.impl.root.ViewFolderFlowNode import io.element.android.libraries.architecture.createNode @ContributesBinding(AppScope::class) @@ -25,7 +25,7 @@ class DefaultViewFolderEntryPoint : ViewFolderEntryPoint { return object : ViewFolderEntryPoint.NodeBuilder { override fun params(params: ViewFolderEntryPoint.Params): ViewFolderEntryPoint.NodeBuilder { - plugins += ViewFolderRootNode.Inputs(params.rootPath) + plugins += ViewFolderFlowNode.Inputs(params.rootPath) return this } @@ -35,7 +35,7 @@ class DefaultViewFolderEntryPoint : ViewFolderEntryPoint { } override fun build(): Node { - return parentNode.createNode(buildContext, plugins) + return parentNode.createNode(buildContext, plugins) } } } diff --git a/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/root/ViewFolderRootNode.kt b/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/root/ViewFolderFlowNode.kt similarity index 98% rename from features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/root/ViewFolderRootNode.kt rename to features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/root/ViewFolderFlowNode.kt index 984c2e1f10..2eb6712364 100644 --- a/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/root/ViewFolderRootNode.kt +++ b/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/root/ViewFolderFlowNode.kt @@ -34,10 +34,10 @@ import kotlinx.parcelize.Parcelize @ContributesNode(AppScope::class) @Inject -class ViewFolderRootNode( +class ViewFolderFlowNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, -) : BaseFlowNode( +) : BaseFlowNode( backstack = BackStack( initialElement = NavTarget.Root, savedStateMap = buildContext.savedStateMap, From 12c75905f4da3d2c2e2285aa07317a73007942b8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 10:38:16 +0200 Subject: [PATCH 057/145] Rename Node to follow naming convention --- .../mediaviewer/impl/DefaultMediaGalleryEntryPoint.kt | 4 ++-- ...MediaGalleryRootNode.kt => MediaGalleryFlowNode.kt} | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) rename libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/{MediaGalleryRootNode.kt => MediaGalleryFlowNode.kt} (95%) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPoint.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPoint.kt index e9e62131aa..0b6c2cc6cb 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPoint.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPoint.kt @@ -15,7 +15,7 @@ import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.createNode import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint -import io.element.android.libraries.mediaviewer.impl.gallery.root.MediaGalleryRootNode +import io.element.android.libraries.mediaviewer.impl.gallery.root.MediaGalleryFlowNode @ContributesBinding(AppScope::class) @Inject @@ -30,7 +30,7 @@ class DefaultMediaGalleryEntryPoint : MediaGalleryEntryPoint { } override fun build(): Node { - return parentNode.createNode(buildContext, plugins) + return parentNode.createNode(buildContext, plugins) } } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryRootNode.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryFlowNode.kt similarity index 95% rename from libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryRootNode.kt rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryFlowNode.kt index 66cd9e14e1..4f899ac0f5 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryRootNode.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryFlowNode.kt @@ -41,11 +41,11 @@ import kotlinx.parcelize.Parcelize @ContributesNode(RoomScope::class) @Inject -class MediaGalleryRootNode( +class MediaGalleryFlowNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, private val mediaViewerEntryPoint: MediaViewerEntryPoint -) : BaseFlowNode( +) : BaseFlowNode( backstack = BackStack( initialElement = NavTarget.Root, savedStateMap = buildContext.savedStateMap, @@ -87,11 +87,11 @@ class MediaGalleryRootNode( NavTarget.Root -> { val callback = object : MediaGalleryNode.Callback { override fun onBackClick() { - this@MediaGalleryRootNode.onBackClick() + this@MediaGalleryFlowNode.onBackClick() } override fun onViewInTimeline(eventId: EventId) { - this@MediaGalleryRootNode.onViewInTimeline(eventId) + this@MediaGalleryFlowNode.onViewInTimeline(eventId) } override fun onItemClick(item: MediaItem.Event) { @@ -122,7 +122,7 @@ class MediaGalleryRootNode( } override fun onViewInTimeline(eventId: EventId) { - this@MediaGalleryRootNode.onViewInTimeline(eventId) + this@MediaGalleryFlowNode.onViewInTimeline(eventId) } } mediaViewerEntryPoint.nodeBuilder(this, buildContext) From cbe2f0684b1cbe69b4a10e450b5386f92d46ec57 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 10:50:34 +0200 Subject: [PATCH 058/145] Add Konsist test. --- .../android/tests/konsist/KonsistClassNameTest.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt index d24a489c6a..8a0e6d0966 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt @@ -20,6 +20,7 @@ import com.lemonappdev.konsist.api.ext.list.withoutName import com.lemonappdev.konsist.api.ext.list.withoutNameStartingWith import com.lemonappdev.konsist.api.verify.assertEmpty import com.lemonappdev.konsist.api.verify.assertTrue +import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.Presenter import org.junit.Test @@ -44,6 +45,16 @@ class KonsistClassNameTest { } } + @Test + fun `Classes extending 'BaseFlowNode' should have 'FlowNode' suffix`() { + Konsist.scopeFromProject() + .classes() + .withAllParentsOf(BaseFlowNode::class) + .assertTrue { + it.name.endsWith("FlowNode") + } + } + @Test fun `Classes extending 'PreviewParameterProvider' name MUST end with 'Provider' and MUST contain provided class name`() { Konsist.scopeFromProduction() From b2c993b1c2b910905d68bce282a4950a1ac172ce Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Sep 2025 10:05:03 +0000 Subject: [PATCH 059/145] Update dependency org.matrix.rustcomponents:sdk-android to v25.9.16 --- 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 9c0ec6c01b..49d7b3996c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -176,7 +176,7 @@ jsoup = "org.jsoup:jsoup:1.21.2" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.1.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.15" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.16" 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 f28b53d85ecf58f7c1f0ad765ae4f7c2bac6b7e9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 12:27:27 +0200 Subject: [PATCH 060/145] Remove useless line of code. --- .../io/element/android/libraries/matrix/impl/RustMatrixClient.kt | 1 - 1 file changed, 1 deletion(-) 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 e193d8f37d..24407ab6f9 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 @@ -287,7 +287,6 @@ class RustMatrixClient( } override suspend fun getRoom(roomId: RoomId): BaseRoom? = withContext(sessionDispatcher) { - innerClient.rooms() roomFactory.getBaseRoom(roomId) } From a69cf58a5b59cd71f3aacb8eeba8e5230f6f1c1c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Sep 2025 11:55:59 +0200 Subject: [PATCH 061/145] Add test on DefaultSpaceEntryPoint --- .../features/space/impl/SpacePresenter.kt | 2 +- .../space/impl/DefaultSpaceEntryPointTest.kt | 62 +++++++++++++++++++ .../architecture/AssistedNodeFactory.kt | 2 +- .../libraries/architecture/NodeFactories.kt | 3 +- .../tests/testutils/node/TestParentNode.kt | 50 +++++++++++++++ 5 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt create mode 100644 tests/testutils/src/main/kotlin/io/element/android/tests/testutils/node/TestParentNode.kt diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt index 95597371a6..b24d9c76ff 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpacePresenter.kt @@ -37,7 +37,7 @@ class SpacePresenter( private val seenInvitesStore: SeenInvitesStore, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(inputs: SpaceEntryPoint.Inputs): SpacePresenter } diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt new file mode 100644 index 0000000000..a0afb36630 --- /dev/null +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.space.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.invite.test.InMemorySeenInvitesStore +import io.element.android.features.space.api.SpaceEntryPoint +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.spaces.FakeSpaceRoomList +import io.element.android.libraries.matrix.test.spaces.FakeSpaceService +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultSpaceEntryPointTest { + @Test + fun `test DefaultSpaceEntryPoint`() { + val entryPoint = DefaultSpaceEntryPoint() + val nodeInputs = SpaceEntryPoint.Inputs(A_ROOM_ID) + val parentNode = TestParentNode.create { buildContext, plugins -> + SpaceNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { inputs -> + assertThat(inputs).isEqualTo(nodeInputs) + SpacePresenter( + inputs = inputs, + client = FakeMatrixClient( + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ) + ), + seenInvitesStore = InMemorySeenInvitesStore(), + ) + }, + ) + } + val callback = object : SpaceEntryPoint.Callback { + override fun onOpenRoom(roomId: RoomId) { + lambdaError() + } + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .inputs(nodeInputs) + .callback(callback) + .build() + assertThat(result).isInstanceOf(SpaceNode::class.java) + assertThat(result.plugins).contains(nodeInputs) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/AssistedNodeFactory.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/AssistedNodeFactory.kt index 508038fb4c..d333eae1cd 100644 --- a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/AssistedNodeFactory.kt +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/AssistedNodeFactory.kt @@ -11,6 +11,6 @@ import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin -interface AssistedNodeFactory { +fun interface AssistedNodeFactory { fun create(buildContext: BuildContext, plugins: List): NODE } diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt index 4bddbc5541..0a3c3c4433 100644 --- a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt @@ -46,8 +46,7 @@ inline fun NodeFactoriesBindings.createNode( return node as N } -// @BindingContainer -interface NodeFactoriesBindings { +fun interface NodeFactoriesBindings { @Multibinds fun nodeFactories(): Map, AssistedNodeFactory<*>> } diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/node/TestParentNode.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/node/TestParentNode.kt new file mode 100644 index 0000000000..a0183e8755 --- /dev/null +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/node/TestParentNode.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.tests.testutils.node + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.EmptyNodeView +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import io.element.android.libraries.architecture.AssistedNodeFactory +import io.element.android.libraries.architecture.NodeFactoriesBindings +import io.element.android.libraries.di.DependencyInjectionGraphOwner +import kotlin.reflect.KClass + +/** + * A parent Node that can create a single type of child Node using the provided factory. + * This is useful to test a Feature entry point, by providing a fake parent that can create a + * child Node. + */ +class TestParentNode( + private val childNodeClass: KClass, + private val childNodeFactory: (buildContext: BuildContext, plugins: List) -> Child, +) : DependencyInjectionGraphOwner, + Node( + buildContext = BuildContext.Companion.root(savedStateMap = null), + plugins = emptyList(), + view = EmptyNodeView, + ) { + + override val graph: NodeFactoriesBindings = NodeFactoriesBindings { + mapOf( + childNodeClass to AssistedNodeFactory { buildContext, plugins -> + childNodeFactory(buildContext, plugins) + } + ) + } + + companion object { + // Inline factory function with reified type parameter + inline fun create( + noinline childNodeFactory: (buildContext: BuildContext, plugins: List) -> Child, + ): TestParentNode { + return TestParentNode(Child::class, childNodeFactory) + } + } +} From 9b24e041019d60ad699cc0d07a6bc252bef49eda Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Sep 2025 18:41:06 +0200 Subject: [PATCH 062/145] Introduce DependencyHandlerScope.testCommonDependencies() --- .../kotlin/extension/DependencyHandleScope.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index 440f9d338b..53dcd8f16e 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -19,6 +19,7 @@ import org.gradle.kotlin.dsl.closureOf import org.gradle.kotlin.dsl.project private fun DependencyHandlerScope.implementation(dependency: Any) = dependencies.add("implementation", dependency) +private fun DependencyHandlerScope.testImplementation(dependency: Any) = dependencies.add("testImplementation", dependency) internal fun DependencyHandler.implementation(dependency: Any) = add("implementation", dependency) // Implementation + config block @@ -32,6 +33,21 @@ private fun DependencyHandlerScope.androidTestImplementation(dependency: Any) = private fun DependencyHandlerScope.debugImplementation(dependency: Any) = dependencies.add("debugImplementation", dependency) private fun DependencyHandlerScope.releaseImplementation(dependency: Any) = dependencies.add("releaseImplementation", dependency) +/** + * Dependencies used for unit tests. + */ +fun DependencyHandlerScope.testCommonDependencies(libs: LibrariesForLibs) { + testImplementation(libs.androidx.test.ext.junit) + testImplementation(libs.coroutines.test) + testImplementation(libs.molecule.runtime) + testImplementation(libs.test.junit) + testImplementation(libs.test.mockk) + testImplementation(libs.test.robolectric) + testImplementation(libs.test.truth) + testImplementation(libs.test.turbine) + testImplementation(project(":tests:testutils")) +} + /** * Dependencies used by all the modules */ From bc9ba9ae067f1fd4854cea3c372a0d2837386437 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Sep 2025 18:42:40 +0200 Subject: [PATCH 063/145] Add test on DefaultAnalyticsEntryPoint --- features/analytics/impl/build.gradle.kts | 9 +---- .../impl/DefaultAnalyticsEntryPointTest.kt | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/DefaultAnalyticsEntryPointTest.kt diff --git a/features/analytics/impl/build.gradle.kts b/features/analytics/impl/build.gradle.kts index b722196c59..d35db4295e 100644 --- a/features/analytics/impl/build.gradle.kts +++ b/features/analytics/impl/build.gradle.kts @@ -1,3 +1,4 @@ +import extension.testCommonDependencies import extension.setupDependencyInjection /* @@ -30,13 +31,7 @@ dependencies { implementation(libs.androidx.datastore.preferences) implementation(libs.androidx.browser) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.mockk) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.analytics.test) - testImplementation(projects.tests.testutils) } diff --git a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/DefaultAnalyticsEntryPointTest.kt b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/DefaultAnalyticsEntryPointTest.kt new file mode 100644 index 0000000000..a814332994 --- /dev/null +++ b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/DefaultAnalyticsEntryPointTest.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.analytics.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultAnalyticsEntryPointTest { + @Test + fun `test node creation`() { + val entryPoint = DefaultAnalyticsEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + AnalyticsOptInNode( + buildContext = buildContext, + plugins = plugins, + AnalyticsOptInPresenter( + buildMeta = aBuildMeta(), + analyticsService = FakeAnalyticsService() + ) + ) + } + val result = entryPoint.createNode(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(AnalyticsOptInNode::class.java) + } +} From a57501976047db28eea5e6cd2235f2060963ed9c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Sep 2025 19:04:35 +0200 Subject: [PATCH 064/145] Use DependencyHandlerScope.testCommonDependencies() --- app/build.gradle.kts | 9 ++------- appnav/build.gradle.kts | 9 ++------- features/cachecleaner/impl/build.gradle.kts | 6 ++---- features/call/impl/build.gradle.kts | 11 ++--------- .../changeroommemberroles/impl/build.gradle.kts | 11 ++--------- features/createroom/impl/build.gradle.kts | 12 ++---------- features/deactivation/impl/build.gradle.kts | 11 ++--------- features/enterprise/impl-foss/build.gradle.kts | 5 ++--- features/ftue/impl/build.gradle.kts | 11 ++--------- features/home/impl/build.gradle.kts | 11 ++--------- features/invite/impl/build.gradle.kts | 11 ++--------- features/invitepeople/impl/build.gradle.kts | 12 ++---------- features/joinroom/impl/build.gradle.kts | 11 ++--------- features/knockrequests/impl/build.gradle.kts | 11 ++--------- features/leaveroom/impl/build.gradle.kts | 8 ++------ features/licenses/impl/build.gradle.kts | 9 +++------ features/location/api/build.gradle.kts | 4 ++-- features/location/impl/build.gradle.kts | 12 +++--------- features/lockscreen/impl/build.gradle.kts | 12 ++---------- features/login/impl/build.gradle.kts | 12 ++---------- features/logout/impl/build.gradle.kts | 11 ++--------- features/messages/impl/build.gradle.kts | 12 ++---------- features/migration/impl/build.gradle.kts | 9 ++------- features/poll/impl/build.gradle.kts | 11 ++--------- features/preferences/impl/build.gradle.kts | 12 ++---------- features/rageshake/impl/build.gradle.kts | 10 ++-------- features/reportroom/impl/build.gradle.kts | 11 ++--------- features/roomaliasresolver/impl/build.gradle.kts | 11 ++--------- features/roomcall/impl/build.gradle.kts | 10 ++-------- features/roomdetails/impl/build.gradle.kts | 12 ++---------- features/roomdirectory/impl/build.gradle.kts | 11 ++--------- features/roommembermoderation/impl/build.gradle.kts | 11 ++--------- features/securebackup/impl/build.gradle.kts | 11 ++--------- features/share/impl/build.gradle.kts | 11 ++--------- features/signedout/impl/build.gradle.kts | 8 ++------ features/space/impl/build.gradle.kts | 12 ++---------- features/startchat/impl/build.gradle.kts | 12 ++---------- features/userprofile/impl/build.gradle.kts | 12 ++---------- features/userprofile/shared/build.gradle.kts | 12 +++--------- features/verifysession/impl/build.gradle.kts | 11 ++--------- features/viewfolder/impl/build.gradle.kts | 9 ++------- libraries/androidutils/build.gradle.kts | 8 ++------ libraries/architecture/build.gradle.kts | 5 ++--- libraries/cryptography/impl/build.gradle.kts | 4 ++-- libraries/dateformatter/api/build.gradle.kts | 5 +++-- libraries/dateformatter/impl/build.gradle.kts | 8 ++------ libraries/deeplink/impl/build.gradle.kts | 6 ++---- libraries/designsystem/build.gradle.kts | 8 +++----- libraries/eventformatter/impl/build.gradle.kts | 5 ++--- libraries/featureflag/impl/build.gradle.kts | 7 +++---- libraries/fullscreenintent/impl/build.gradle.kts | 12 ++---------- libraries/indicator/impl/build.gradle.kts | 7 ++----- libraries/matrix/api/build.gradle.kts | 4 ++-- libraries/matrix/impl/build.gradle.kts | 8 ++------ libraries/matrixui/build.gradle.kts | 12 ++---------- libraries/mediapickers/api/build.gradle.kts | 7 +++---- libraries/mediaplayer/impl/build.gradle.kts | 8 ++------ libraries/mediaupload/api/build.gradle.kts | 7 ++----- libraries/mediaupload/impl/build.gradle.kts | 7 ++----- libraries/mediaviewer/impl/build.gradle.kts | 13 ++----------- libraries/mediaviewer/test/build.gradle.kts | 5 +++-- libraries/oidc/impl/build.gradle.kts | 10 ++-------- libraries/permissions/impl/build.gradle.kts | 8 ++------ libraries/permissions/noop/build.gradle.kts | 9 +++------ libraries/preferences/api/build.gradle.kts | 5 +++-- libraries/push/impl/build.gradle.kts | 9 ++------- libraries/pushproviders/firebase/build.gradle.kts | 8 ++------ .../pushproviders/unifiedpush/build.gradle.kts | 9 +++------ libraries/pushstore/impl/build.gradle.kts | 8 ++------ libraries/roomselect/impl/build.gradle.kts | 8 ++------ libraries/session-storage/impl/build.gradle.kts | 7 ++----- libraries/textcomposer/impl/build.gradle.kts | 11 ++--------- libraries/troubleshoot/impl/build.gradle.kts | 11 ++--------- libraries/ui-utils/build.gradle.kts | 7 +++---- libraries/usersearch/impl/build.gradle.kts | 7 ++----- libraries/voiceplayer/impl/build.gradle.kts | 9 ++------- libraries/voicerecorder/impl/build.gradle.kts | 8 ++------ libraries/wellknown/impl/build.gradle.kts | 7 ++----- .../main/kotlin/extension/DependencyHandleScope.kt | 10 +++++++++- services/analytics/impl/build.gradle.kts | 6 ++---- .../analyticsproviders/posthog/build.gradle.kts | 7 ++----- services/apperror/impl/build.gradle.kts | 6 ++---- services/appnavstate/impl/build.gradle.kts | 6 ++---- .../Template Module Feature Build Gradle Impl.kts | 7 ++----- 84 files changed, 187 insertions(+), 569 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 14203ec711..9be152e9e7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -24,6 +24,7 @@ import extension.koverDependencies import extension.locales import extension.setupDependencyInjection import extension.setupKover +import extension.testCommonDependencies import java.util.Locale plugins { @@ -290,15 +291,9 @@ dependencies { implementation(libs.matrix.emojibase.bindings) - testImplementation(libs.test.junit) - testImplementation(libs.test.robolectric) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.toolbox.test) - testImplementation(projects.tests.testutils) koverDependencies() } diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index 7c29626d75..f91a194e04 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -9,6 +9,7 @@ import extension.allFeaturesApi import extension.setupDependencyInjection +import extension.testCommonDependencies plugins { id("io.element.android-compose-library") @@ -48,12 +49,7 @@ dependencies { implementation(projects.services.appnavstate.api) implementation(projects.services.analytics.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.robolectric) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(projects.features.login.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.oidc.test) @@ -61,7 +57,6 @@ dependencies { testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushproviders.test) testImplementation(projects.features.networkmonitor.test) - testImplementation(projects.tests.testutils) testImplementation(projects.features.rageshake.test) testImplementation(projects.services.appnavstate.test) testImplementation(projects.services.analytics.test) diff --git a/features/cachecleaner/impl/build.gradle.kts b/features/cachecleaner/impl/build.gradle.kts index 45cc5fe09b..8603de6322 100644 --- a/features/cachecleaner/impl/build.gradle.kts +++ b/features/cachecleaner/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -22,8 +23,5 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.architecture) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.truth) - testImplementation(projects.tests.testutils) + testCommonDependencies(libs) } diff --git a/features/call/impl/build.gradle.kts b/features/call/impl/build.gradle.kts index 0c9ae5a4b0..42bfa59a51 100644 --- a/features/call/impl/build.gradle.kts +++ b/features/call/impl/build.gradle.kts @@ -1,6 +1,7 @@ import extension.buildConfigFieldStr import extension.readLocalProperty import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -87,12 +88,7 @@ dependencies { implementation(libs.element.call.embedded) api(projects.features.call.api) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.mockk) + testCommonDependencies(libs, true) testImplementation(projects.features.call.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.preferences.test) @@ -100,7 +96,4 @@ dependencies { testImplementation(projects.libraries.push.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.appnavstate.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/changeroommemberroles/impl/build.gradle.kts b/features/changeroommemberroles/impl/build.gradle.kts index fe5cbe3333..be2bf17979 100644 --- a/features/changeroommemberroles/impl/build.gradle.kts +++ b/features/changeroommemberroles/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2025 New Vector Ltd. @@ -37,15 +38,7 @@ dependencies { implementation(projects.libraries.uiStrings) implementation(projects.services.analytics.api) + testCommonDependencies(libs, true) testImplementation(projects.services.analytics.test) - testImplementation(libs.test.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.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/createroom/impl/build.gradle.kts b/features/createroom/impl/build.gradle.kts index faf293c54d..712ce110f8 100644 --- a/features/createroom/impl/build.gradle.kts +++ b/features/createroom/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -43,13 +44,7 @@ dependencies { implementation(projects.features.invitepeople.api) api(projects.features.createroom.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.mockk) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.services.analytics.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.mediapickers.test) @@ -58,7 +53,4 @@ dependencies { testImplementation(projects.libraries.usersearch.test) testImplementation(projects.features.startchat.test) testImplementation(projects.libraries.featureflag.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/deactivation/impl/build.gradle.kts b/features/deactivation/impl/build.gradle.kts index 3908b9d0a4..842206bab7 100644 --- a/features/deactivation/impl/build.gradle.kts +++ b/features/deactivation/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -34,14 +35,6 @@ dependencies { implementation(projects.libraries.uiStrings) api(projects.features.deactivation.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) } diff --git a/features/enterprise/impl-foss/build.gradle.kts b/features/enterprise/impl-foss/build.gradle.kts index 0b32b5d97c..956c0e1900 100644 --- a/features/enterprise/impl-foss/build.gradle.kts +++ b/features/enterprise/impl-foss/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -22,8 +23,6 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) } diff --git a/features/ftue/impl/build.gradle.kts b/features/ftue/impl/build.gradle.kts index 44ccf323b9..8f940ed29a 100644 --- a/features/ftue/impl/build.gradle.kts +++ b/features/ftue/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -46,14 +47,7 @@ dependencies { implementation(projects.services.toolbox.api) implementation(projects.appconfig) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.analytics.noop) @@ -61,5 +55,4 @@ dependencies { testImplementation(projects.libraries.preferences.test) testImplementation(projects.features.lockscreen.test) testImplementation(projects.services.toolbox.test) - testImplementation(projects.tests.testutils) } diff --git a/features/home/impl/build.gradle.kts b/features/home/impl/build.gradle.kts index f0ebe6c02d..b6a83775fc 100644 --- a/features/home/impl/build.gradle.kts +++ b/features/home/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -58,14 +59,7 @@ dependencies { implementation(projects.libraries.previewutils) api(projects.features.home.api) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.features.invite.test) testImplementation(projects.features.logout.test) testImplementation(projects.features.networkmonitor.test) @@ -80,5 +74,4 @@ dependencies { testImplementation(projects.libraries.push.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.toolbox.test) - testImplementation(projects.tests.testutils) } diff --git a/features/invite/impl/build.gradle.kts b/features/invite/impl/build.gradle.kts index 6a1cec8056..4caeafb71f 100644 --- a/features/invite/impl/build.gradle.kts +++ b/features/invite/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -36,17 +37,9 @@ dependencies { implementation(projects.services.analytics.api) implementation(projects.libraries.push.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.features.invite.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.push.test) testImplementation(projects.services.analytics.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/invitepeople/impl/build.gradle.kts b/features/invitepeople/impl/build.gradle.kts index 9133700f06..f0fcde6a00 100644 --- a/features/invitepeople/impl/build.gradle.kts +++ b/features/invitepeople/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -37,17 +38,8 @@ dependencies { implementation(projects.services.apperror.api) api(projects.features.invitepeople.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.mockk) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.usersearch.test) testImplementation(projects.services.apperror.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/joinroom/impl/build.gradle.kts b/features/joinroom/impl/build.gradle.kts index 22821a3a84..731a8b3377 100644 --- a/features/joinroom/impl/build.gradle.kts +++ b/features/joinroom/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -38,16 +39,8 @@ dependencies { implementation(projects.libraries.preferences.api) implementation(projects.appconfig) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.features.invite.test) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) testImplementation(projects.libraries.preferences.test) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/knockrequests/impl/build.gradle.kts b/features/knockrequests/impl/build.gradle.kts index 7a93786b08..41fadb00da 100644 --- a/features/knockrequests/impl/build.gradle.kts +++ b/features/knockrequests/impl/build.gradle.kts @@ -6,6 +6,7 @@ */ import extension.setupDependencyInjection +import extension.testCommonDependencies plugins { id("io.element.android-compose-library") @@ -33,15 +34,7 @@ dependencies { implementation(projects.libraries.designsystem) implementation(projects.libraries.featureflag.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) testImplementation(projects.libraries.featureflag.test) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/leaveroom/impl/build.gradle.kts b/features/leaveroom/impl/build.gradle.kts index edc663475f..81aedb2025 100644 --- a/features/leaveroom/impl/build.gradle.kts +++ b/features/leaveroom/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -26,13 +27,8 @@ dependencies { implementation(projects.libraries.uiStrings) implementation(projects.libraries.push.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) + testCommonDependencies(libs) testImplementation(libs.coroutines.core) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.push.test) - testImplementation(projects.tests.testutils) } diff --git a/features/licenses/impl/build.gradle.kts b/features/licenses/impl/build.gradle.kts index 1fecb66b90..59ad326b6f 100644 --- a/features/licenses/impl/build.gradle.kts +++ b/features/licenses/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -26,12 +27,8 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.uiStrings) api(projects.features.licenses.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) + + testCommonDependencies(libs) testImplementation(libs.coroutines.core) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) } diff --git a/features/location/api/build.gradle.kts b/features/location/api/build.gradle.kts index 4ce33a748a..e4d5c4e886 100644 --- a/features/location/api/build.gradle.kts +++ b/features/location/api/build.gradle.kts @@ -8,6 +8,7 @@ import config.BuildTimeConfig import extension.buildConfigFieldStr import extension.readLocalProperty +import extension.testCommonDependencies plugins { id("io.element.android-compose-library") @@ -70,6 +71,5 @@ dependencies { implementation(projects.libraries.uiStrings) implementation(libs.coil.compose) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) + testCommonDependencies(libs) } diff --git a/features/location/impl/build.gradle.kts b/features/location/impl/build.gradle.kts index 577132baca..43f6bba0d0 100644 --- a/features/location/impl/build.gradle.kts +++ b/features/location/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -37,17 +38,10 @@ dependencies { implementation(projects.services.analytics.api) implementation(libs.accompanist.permission) implementation(projects.libraries.uiStrings) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.testtags) testImplementation(projects.services.analytics.test) testImplementation(projects.features.messages.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/lockscreen/impl/build.gradle.kts b/features/lockscreen/impl/build.gradle.kts index ff5f629e86..011d4919e7 100644 --- a/features/lockscreen/impl/build.gradle.kts +++ b/features/lockscreen/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -44,21 +45,12 @@ dependencies { implementation(libs.androidx.datastore.preferences) implementation(libs.androidx.biometric) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) - testImplementation(libs.androidx.compose.ui.test.junit) - testImplementation(libs.androidx.test.ext.junit) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) testImplementation(projects.libraries.cryptography.test) testImplementation(projects.libraries.cryptography.impl) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.appnavstate.test) testImplementation(projects.features.logout.test) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/login/impl/build.gradle.kts b/features/login/impl/build.gradle.kts index 3873ea70d7..314907c04a 100644 --- a/features/login/impl/build.gradle.kts +++ b/features/login/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -48,14 +49,7 @@ dependencies { implementation(libs.serialization.json) api(projects.features.login.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) + testCommonDependencies(libs, true) testImplementation(projects.features.login.test) testImplementation(projects.features.enterprise.test) testImplementation(projects.libraries.featureflag.test) @@ -63,6 +57,4 @@ dependencies { testImplementation(projects.libraries.oidc.test) testImplementation(projects.libraries.permissions.test) testImplementation(projects.libraries.wellknown.test) - testImplementation(projects.tests.testutils) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/logout/impl/build.gradle.kts b/features/logout/impl/build.gradle.kts index 09fdc1bd96..b999d10db2 100644 --- a/features/logout/impl/build.gradle.kts +++ b/features/logout/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -35,15 +36,7 @@ dependencies { implementation(projects.libraries.dateformatter.api) api(projects.features.logout.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.featureflag.test) - testImplementation(projects.tests.testutils) } diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index 15e087bac4..d05ede00ab 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -70,11 +71,7 @@ dependencies { implementation(projects.features.knockrequests.api) implementation(projects.features.roommembermoderation.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.dateformatter.test) testImplementation(projects.libraries.push.test) @@ -83,7 +80,6 @@ dependencies { testImplementation(projects.features.messages.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.toolbox.test) - testImplementation(projects.tests.testutils) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.mediapickers.test) @@ -93,10 +89,6 @@ dependencies { testImplementation(projects.libraries.mediaplayer.test) testImplementation(projects.libraries.mediaviewer.test) testImplementation(projects.libraries.testtags) - testImplementation(libs.test.mockk) - testImplementation(libs.test.robolectric) testImplementation(projects.features.poll.test) - testImplementation(libs.androidx.compose.ui.test.junit) testImplementation(projects.libraries.eventformatter.test) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/migration/impl/build.gradle.kts b/features/migration/impl/build.gradle.kts index 0a9048a5c6..dd445624b9 100644 --- a/features/migration/impl/build.gradle.kts +++ b/features/migration/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -29,15 +30,9 @@ dependencies { implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.uiStrings) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.libraries.preferences.test) - testImplementation(projects.tests.testutils) testImplementation(projects.features.rageshake.test) } diff --git a/features/poll/impl/build.gradle.kts b/features/poll/impl/build.gradle.kts index 200fe0f4b8..99ebefa71c 100644 --- a/features/poll/impl/build.gradle.kts +++ b/features/poll/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -35,18 +36,10 @@ dependencies { implementation(projects.libraries.dateformatter.api) implementation(projects.libraries.uiStrings) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.analytics.test) testImplementation(projects.features.messages.test) - testImplementation(projects.tests.testutils) testImplementation(projects.libraries.dateformatter.test) testImplementation(projects.features.poll.test) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index d6c716ca87..d1041c1ba7 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -1,6 +1,7 @@ import config.BuildTimeConfig import extension.buildConfigFieldStr import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -91,13 +92,7 @@ dependencies { implementation(platform(libs.network.okhttp.bom)) implementation(libs.network.okhttp) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.mockk) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.mediapickers.test) @@ -114,7 +109,4 @@ dependencies { testImplementation(projects.libraries.pushproviders.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.toolbox.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/rageshake/impl/build.gradle.kts b/features/rageshake/impl/build.gradle.kts index ea4eb33ba6..717da71e1f 100644 --- a/features/rageshake/impl/build.gradle.kts +++ b/features/rageshake/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -45,19 +46,12 @@ dependencies { implementation(libs.coil) implementation(libs.coil.compose) - testImplementation(libs.test.junit) - testImplementation(libs.test.robolectric) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.mockk) + testCommonDependencies(libs) testImplementation(projects.features.enterprise.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.features.rageshake.test) testImplementation(projects.libraries.preferences.test) - testImplementation(projects.tests.testutils) testImplementation(projects.services.toolbox.test) testImplementation(libs.network.mockwebserver) } diff --git a/features/reportroom/impl/build.gradle.kts b/features/reportroom/impl/build.gradle.kts index 797fa08741..99d65612bd 100644 --- a/features/reportroom/impl/build.gradle.kts +++ b/features/reportroom/impl/build.gradle.kts @@ -6,6 +6,7 @@ */ import extension.setupDependencyInjection +import extension.testCommonDependencies plugins { id("io.element.android-compose-library") @@ -32,14 +33,6 @@ dependencies { implementation(projects.libraries.designsystem) implementation(projects.libraries.uiStrings) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) - testImplementation(libs.test.robolectric) } diff --git a/features/roomaliasresolver/impl/build.gradle.kts b/features/roomaliasresolver/impl/build.gradle.kts index f70f2a6f7b..45cf32f661 100644 --- a/features/roomaliasresolver/impl/build.gradle.kts +++ b/features/roomaliasresolver/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -33,14 +34,6 @@ dependencies { implementation(projects.libraries.designsystem) implementation(projects.libraries.uiStrings) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/roomcall/impl/build.gradle.kts b/features/roomcall/impl/build.gradle.kts index 5c69ffed36..7a6a3cf0a6 100644 --- a/features/roomcall/impl/build.gradle.kts +++ b/features/roomcall/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -26,15 +27,8 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.features.call.test) testImplementation(projects.features.enterprise.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts index fa5569a873..882058ef48 100644 --- a/features/roomdetails/impl/build.gradle.kts +++ b/features/roomdetails/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -58,13 +59,7 @@ dependencies { implementation(projects.features.changeroommemberroles.api) implementation(projects.features.invitepeople.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.mockk) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.mediapickers.test) @@ -72,9 +67,6 @@ dependencies { testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.usersearch.test) testImplementation(projects.libraries.featureflag.test) - testImplementation(projects.tests.testutils) testImplementation(projects.features.startchat.test) testImplementation(projects.services.analytics.test) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/roomdirectory/impl/build.gradle.kts b/features/roomdirectory/impl/build.gradle.kts index 813d6be1ff..ec858ced09 100644 --- a/features/roomdirectory/impl/build.gradle.kts +++ b/features/roomdirectory/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -35,14 +36,6 @@ dependencies { implementation(projects.libraries.testtags) implementation(projects.services.analytics.api) - testImplementation(libs.test.junit) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) - testImplementation(libs.test.robolectric) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) } diff --git a/features/roommembermoderation/impl/build.gradle.kts b/features/roommembermoderation/impl/build.gradle.kts index 7208b5985f..a58b0ce02f 100644 --- a/features/roommembermoderation/impl/build.gradle.kts +++ b/features/roommembermoderation/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2025 New Vector Ltd. @@ -32,16 +33,8 @@ dependencies { implementation(projects.libraries.uiStrings) implementation(projects.services.analytics.compose) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) testImplementation(projects.services.analytics.test) - testImplementation(libs.test.robolectric) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) testImplementation(projects.libraries.testtags) } diff --git a/features/securebackup/impl/build.gradle.kts b/features/securebackup/impl/build.gradle.kts index 399547108b..92a6013580 100644 --- a/features/securebackup/impl/build.gradle.kts +++ b/features/securebackup/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -38,14 +39,6 @@ dependencies { api(libs.statemachine) api(projects.features.securebackup.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) - testImplementation(libs.androidx.compose.ui.test.junit) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/share/impl/build.gradle.kts b/features/share/impl/build.gradle.kts index 3f8ef152fb..4c62a06352 100644 --- a/features/share/impl/build.gradle.kts +++ b/features/share/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -41,16 +42,8 @@ dependencies { api(libs.statemachine) api(projects.features.share.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) - testImplementation(libs.androidx.compose.ui.test.junit) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.preferences.test) - testImplementation(projects.tests.testutils) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/signedout/impl/build.gradle.kts b/features/signedout/impl/build.gradle.kts index f4da2e48a4..f314cb8283 100644 --- a/features/signedout/impl/build.gradle.kts +++ b/features/signedout/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -27,12 +28,7 @@ dependencies { implementation(projects.libraries.designsystem) implementation(projects.libraries.uiStrings) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.sessionStorage.test) - testImplementation(projects.tests.testutils) } diff --git a/features/space/impl/build.gradle.kts b/features/space/impl/build.gradle.kts index b41f8ebc93..b6afbdcb05 100644 --- a/features/space/impl/build.gradle.kts +++ b/features/space/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2025 New Vector Ltd. @@ -40,18 +41,9 @@ dependencies { implementation(projects.libraries.previewutils) api(projects.features.space.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.mockk) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.services.analytics.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.featureflag.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) testImplementation(projects.features.invite.test) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/startchat/impl/build.gradle.kts b/features/startchat/impl/build.gradle.kts index 42d5263d58..8ba7593b36 100644 --- a/features/startchat/impl/build.gradle.kts +++ b/features/startchat/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -43,13 +44,7 @@ dependencies { implementation(projects.features.createroom.api) api(projects.features.startchat.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.mockk) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.services.analytics.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.mediapickers.test) @@ -58,7 +53,4 @@ dependencies { testImplementation(projects.libraries.usersearch.test) testImplementation(projects.features.startchat.test) testImplementation(projects.libraries.featureflag.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/userprofile/impl/build.gradle.kts b/features/userprofile/impl/build.gradle.kts index 0805f0d7fc..f0c214c22e 100644 --- a/features/userprofile/impl/build.gradle.kts +++ b/features/userprofile/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -41,17 +42,8 @@ dependencies { implementation(projects.features.startchat.api) implementation(projects.services.analytics.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.mockk) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.features.startchat.test) testImplementation(projects.features.enterprise.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/userprofile/shared/build.gradle.kts b/features/userprofile/shared/build.gradle.kts index c49b78866f..95f64154cf 100644 --- a/features/userprofile/shared/build.gradle.kts +++ b/features/userprofile/shared/build.gradle.kts @@ -1,3 +1,5 @@ +import extension.testCommonDependencies + /* * Copyright 2024 New Vector Ltd. * @@ -38,14 +40,6 @@ dependencies { implementation(projects.features.startchat.api) implementation(projects.services.analytics.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/verifysession/impl/build.gradle.kts b/features/verifysession/impl/build.gradle.kts index b318b10fce..13e9010e7f 100644 --- a/features/verifysession/impl/build.gradle.kts +++ b/features/verifysession/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -37,17 +38,9 @@ dependencies { api(libs.statemachine) api(projects.features.verifysession.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.features.logout.test) testImplementation(projects.libraries.dateformatter.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.preferences.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/features/viewfolder/impl/build.gradle.kts b/features/viewfolder/impl/build.gradle.kts index 023f3c5762..0c7ef17b22 100644 --- a/features/viewfolder/impl/build.gradle.kts +++ b/features/viewfolder/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -26,12 +27,6 @@ dependencies { implementation(projects.libraries.uiStrings) api(projects.features.viewfolder.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.robolectric) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(projects.tests.testutils) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) } diff --git a/libraries/androidutils/build.gradle.kts b/libraries/androidutils/build.gradle.kts index d35fc0c4bd..ac1e317b48 100644 --- a/libraries/androidutils/build.gradle.kts +++ b/libraries/androidutils/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -33,12 +34,7 @@ dependencies { implementation(libs.androidx.datastore.preferences) api(libs.androidx.browser) - testImplementation(projects.tests.testutils) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.robolectric) - testImplementation(libs.androidx.test.ext.junit) + testCommonDependencies(libs) testImplementation(libs.coroutines.core) - testImplementation(libs.coroutines.test) testImplementation(projects.services.toolbox.test) } diff --git a/libraries/architecture/build.gradle.kts b/libraries/architecture/build.gradle.kts index e481aff77a..55b79abca0 100644 --- a/libraries/architecture/build.gradle.kts +++ b/libraries/architecture/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -25,7 +26,5 @@ dependencies { api(libs.androidx.lifecycle.runtime) api(libs.molecule.runtime) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.truth) + testCommonDependencies(libs) } diff --git a/libraries/cryptography/impl/build.gradle.kts b/libraries/cryptography/impl/build.gradle.kts index f15c070585..5e130b64e2 100644 --- a/libraries/cryptography/impl/build.gradle.kts +++ b/libraries/cryptography/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -21,6 +22,5 @@ dependencies { implementation(projects.libraries.di) api(projects.libraries.cryptography.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) + testCommonDependencies(libs) } diff --git a/libraries/dateformatter/api/build.gradle.kts b/libraries/dateformatter/api/build.gradle.kts index 88fd41f039..cebb9d4049 100644 --- a/libraries/dateformatter/api/build.gradle.kts +++ b/libraries/dateformatter/api/build.gradle.kts @@ -1,3 +1,5 @@ +import extension.testCommonDependencies + /* * Copyright 2022-2024 New Vector Ltd. * @@ -13,7 +15,6 @@ android { namespace = "io.element.android.libraries.dateformatter.api" dependencies { - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) + testCommonDependencies(libs) } } diff --git a/libraries/dateformatter/impl/build.gradle.kts b/libraries/dateformatter/impl/build.gradle.kts index 69e311ac8e..72da2f81f6 100644 --- a/libraries/dateformatter/impl/build.gradle.kts +++ b/libraries/dateformatter/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -40,13 +41,8 @@ android { api(projects.libraries.dateformatter.api) api(libs.datetime) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs, true) testImplementation(projects.libraries.dateformatter.test) testImplementation(projects.services.toolbox.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) } } diff --git a/libraries/deeplink/impl/build.gradle.kts b/libraries/deeplink/impl/build.gradle.kts index 8c652037c5..074e144b3a 100644 --- a/libraries/deeplink/impl/build.gradle.kts +++ b/libraries/deeplink/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -28,9 +29,6 @@ dependencies { implementation(projects.libraries.uiStrings) implementation(projects.services.toolbox.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) } diff --git a/libraries/designsystem/build.gradle.kts b/libraries/designsystem/build.gradle.kts index 0d1efa1ed1..c2eec20b8c 100644 --- a/libraries/designsystem/build.gradle.kts +++ b/libraries/designsystem/build.gradle.kts @@ -1,3 +1,5 @@ +import extension.testCommonDependencies + /* * Copyright 2022-2024 New Vector Ltd. * @@ -42,10 +44,6 @@ android { ksp(libs.showkase.processor) implementation(libs.showkase) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) } } diff --git a/libraries/eventformatter/impl/build.gradle.kts b/libraries/eventformatter/impl/build.gradle.kts index 2f97cab31b..3b726da654 100644 --- a/libraries/eventformatter/impl/build.gradle.kts +++ b/libraries/eventformatter/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -32,9 +33,7 @@ dependencies { implementation(projects.services.toolbox.api) api(projects.libraries.eventformatter.api) + testCommonDependencies(libs) testImplementation(projects.services.toolbox.impl) - testImplementation(libs.test.junit) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) testImplementation(projects.libraries.matrix.test) } diff --git a/libraries/featureflag/impl/build.gradle.kts b/libraries/featureflag/impl/build.gradle.kts index 5886e01c94..c54f95a293 100644 --- a/libraries/featureflag/impl/build.gradle.kts +++ b/libraries/featureflag/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -27,9 +28,7 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.preferences.api) implementation(libs.coroutines.core) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) } diff --git a/libraries/fullscreenintent/impl/build.gradle.kts b/libraries/fullscreenintent/impl/build.gradle.kts index 40a65d48e8..2ccb7f80b8 100644 --- a/libraries/fullscreenintent/impl/build.gradle.kts +++ b/libraries/fullscreenintent/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -27,19 +28,10 @@ dependencies { implementation(projects.services.toolbox.api) implementation(libs.androidx.datastore.preferences) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(projects.tests.testutils) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.permissions.test) testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.testtags) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.mockk) - testImplementation(libs.androidx.compose.ui.test.junit) testImplementation(projects.services.toolbox.test) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/libraries/indicator/impl/build.gradle.kts b/libraries/indicator/impl/build.gradle.kts index 9a75cbee26..2596b9fe67 100644 --- a/libraries/indicator/impl/build.gradle.kts +++ b/libraries/indicator/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -26,11 +27,7 @@ dependencies { api(projects.libraries.indicator.api) + testCommonDependencies(libs) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.turbine) - testImplementation(libs.test.truth) } diff --git a/libraries/matrix/api/build.gradle.kts b/libraries/matrix/api/build.gradle.kts index 272527dc9f..04a45654b2 100644 --- a/libraries/matrix/api/build.gradle.kts +++ b/libraries/matrix/api/build.gradle.kts @@ -1,6 +1,7 @@ import config.BuildTimeConfig import extension.buildConfigFieldStr import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -54,7 +55,6 @@ dependencies { implementation(libs.coroutines.core) api(projects.libraries.architecture) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) } diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 757d7aa1fc..33ab700022 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -41,9 +42,7 @@ dependencies { implementation(libs.serialization.json) implementation(libs.kotlinx.collections.immutable) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.preferences.test) @@ -51,7 +50,4 @@ dependencies { testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.toolbox.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.turbine) } diff --git a/libraries/matrixui/build.gradle.kts b/libraries/matrixui/build.gradle.kts index e5fb78eb6d..a500186587 100644 --- a/libraries/matrixui/build.gradle.kts +++ b/libraries/matrixui/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -37,17 +38,8 @@ dependencies { implementation(libs.coil.network.okhttp) implementation(libs.jsoup) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.dateformatter.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.test.mockk) - testImplementation(libs.test.robolectric) - testImplementation(libs.androidx.compose.ui.test.junit) testImplementation(projects.libraries.sessionStorage.test) } diff --git a/libraries/mediapickers/api/build.gradle.kts b/libraries/mediapickers/api/build.gradle.kts index d02c94dd4c..6d24930ac1 100644 --- a/libraries/mediapickers/api/build.gradle.kts +++ b/libraries/mediapickers/api/build.gradle.kts @@ -1,3 +1,5 @@ +import extension.testCommonDependencies + /* * Copyright 2023, 2024 New Vector Ltd. * @@ -18,9 +20,6 @@ android { implementation(projects.libraries.di) implementation(libs.inject) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.truth) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs) } } diff --git a/libraries/mediaplayer/impl/build.gradle.kts b/libraries/mediaplayer/impl/build.gradle.kts index beaeb84dc7..bd6382f86f 100644 --- a/libraries/mediaplayer/impl/build.gradle.kts +++ b/libraries/mediaplayer/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -26,12 +27,7 @@ dependencies { implementation(libs.coroutines.core) - testImplementation(projects.tests.testutils) + testCommonDependencies(libs) testImplementation(projects.libraries.audio.test) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.mockk) - testImplementation(libs.test.turbine) testImplementation(libs.coroutines.core) - testImplementation(libs.coroutines.test) } diff --git a/libraries/mediaupload/api/build.gradle.kts b/libraries/mediaupload/api/build.gradle.kts index ff14dc052f..1219eb6337 100644 --- a/libraries/mediaupload/api/build.gradle.kts +++ b/libraries/mediaupload/api/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -27,12 +28,8 @@ dependencies { implementation(libs.inject) implementation(libs.coroutines.core) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.mediaupload.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.robolectric) } diff --git a/libraries/mediaupload/impl/build.gradle.kts b/libraries/mediaupload/impl/build.gradle.kts index 437473a5b7..64a9e47bdf 100644 --- a/libraries/mediaupload/impl/build.gradle.kts +++ b/libraries/mediaupload/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -39,10 +40,6 @@ dependencies { implementation(libs.coroutines.core) implementation(libs.vanniktech.blurhash) - testImplementation(libs.test.junit) - testImplementation(libs.test.robolectric) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.truth) - testImplementation(projects.tests.testutils) + testCommonDependencies(libs) testImplementation(projects.services.toolbox.test) } diff --git a/libraries/mediaviewer/impl/build.gradle.kts b/libraries/mediaviewer/impl/build.gradle.kts index c47ace5334..acddcfcf76 100644 --- a/libraries/mediaviewer/impl/build.gradle.kts +++ b/libraries/mediaviewer/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -52,21 +53,11 @@ dependencies { implementation(projects.libraries.di) implementation(projects.libraries.matrix.api) + testCommonDependencies(libs, true) testImplementation(projects.libraries.dateformatter.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.mediaviewer.test) testImplementation(projects.services.toolbox.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.mockk) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.turbine) testImplementation(libs.coroutines.core) - testImplementation(libs.coroutines.test) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/libraries/mediaviewer/test/build.gradle.kts b/libraries/mediaviewer/test/build.gradle.kts index cb7bcf671d..45096be999 100644 --- a/libraries/mediaviewer/test/build.gradle.kts +++ b/libraries/mediaviewer/test/build.gradle.kts @@ -1,3 +1,5 @@ +import extension.testCommonDependencies + /* * Copyright 2023, 2024 New Vector Ltd. * @@ -19,6 +21,5 @@ dependencies { implementation(projects.tests.testutils) implementation(projects.libraries.matrix.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) + testCommonDependencies(libs) } diff --git a/libraries/oidc/impl/build.gradle.kts b/libraries/oidc/impl/build.gradle.kts index 4aa270c750..f3c50ed9ab 100644 --- a/libraries/oidc/impl/build.gradle.kts +++ b/libraries/oidc/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -39,14 +40,7 @@ dependencies { implementation(libs.serialization.json) api(projects.libraries.oidc.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.robolectric) - testImplementation(libs.androidx.test.ext.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.permissions.test) - testImplementation(projects.tests.testutils) } diff --git a/libraries/permissions/impl/build.gradle.kts b/libraries/permissions/impl/build.gradle.kts index 3ab164e31a..f7811c649d 100644 --- a/libraries/permissions/impl/build.gradle.kts +++ b/libraries/permissions/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -39,13 +40,8 @@ dependencies { implementation(projects.services.toolbox.api) api(projects.libraries.permissions.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.permissions.test) testImplementation(projects.services.toolbox.test) - testImplementation(projects.tests.testutils) } diff --git a/libraries/permissions/noop/build.gradle.kts b/libraries/permissions/noop/build.gradle.kts index 3eebe43b35..343e913b60 100644 --- a/libraries/permissions/noop/build.gradle.kts +++ b/libraries/permissions/noop/build.gradle.kts @@ -1,3 +1,5 @@ +import extension.testCommonDependencies + /* * Copyright 2023, 2024 New Vector Ltd. * @@ -17,10 +19,5 @@ dependencies { implementation(projects.libraries.architecture) api(projects.libraries.permissions.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(projects.tests.testutils) + testCommonDependencies(libs) } diff --git a/libraries/preferences/api/build.gradle.kts b/libraries/preferences/api/build.gradle.kts index 49c45b7f90..0e86cfc083 100644 --- a/libraries/preferences/api/build.gradle.kts +++ b/libraries/preferences/api/build.gradle.kts @@ -1,3 +1,5 @@ +import extension.testCommonDependencies + /* * Copyright 2023, 2024 New Vector Ltd. * @@ -18,7 +20,6 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(libs.androidx.datastore.preferences) + testCommonDependencies(libs) testImplementation(projects.libraries.preferences.test) - testImplementation(libs.test.truth) - testImplementation(libs.coroutines.test) } diff --git a/libraries/push/impl/build.gradle.kts b/libraries/push/impl/build.gradle.kts index b64c8ebeab..3e186d31da 100644 --- a/libraries/push/impl/build.gradle.kts +++ b/libraries/push/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -63,20 +64,14 @@ dependencies { implementation(projects.services.appnavstate.api) implementation(projects.services.toolbox.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.mockk) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(libs.coil.test) - testImplementation(libs.coroutines.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushproviders.test) testImplementation(projects.libraries.pushstore.test) - testImplementation(projects.tests.testutils) testImplementation(projects.features.call.test) testImplementation(projects.features.lockscreen.test) testImplementation(projects.services.appnavstate.test) diff --git a/libraries/pushproviders/firebase/build.gradle.kts b/libraries/pushproviders/firebase/build.gradle.kts index 4cd929141e..acb12ae150 100644 --- a/libraries/pushproviders/firebase/build.gradle.kts +++ b/libraries/pushproviders/firebase/build.gradle.kts @@ -9,6 +9,7 @@ import config.BuildTimeConfig import extension.setupDependencyInjection +import extension.testCommonDependencies plugins { id("io.element.android-library") @@ -68,17 +69,12 @@ dependencies { exclude(group = "com.google.firebase", module = "firebase-measurement-connector") } - testImplementation(libs.coroutines.test) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs) testImplementation(libs.kotlinx.collections.immutable) testImplementation(projects.features.enterprise.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushstore.test) testImplementation(projects.libraries.sessionStorage.test) - testImplementation(projects.tests.testutils) testImplementation(projects.services.toolbox.test) } diff --git a/libraries/pushproviders/unifiedpush/build.gradle.kts b/libraries/pushproviders/unifiedpush/build.gradle.kts index 49569e624a..c2ec6b3d1c 100644 --- a/libraries/pushproviders/unifiedpush/build.gradle.kts +++ b/libraries/pushproviders/unifiedpush/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -42,18 +43,14 @@ dependencies { // UnifiedPush library api(libs.unifiedpush) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.junit) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + + testCommonDependencies(libs) testImplementation(libs.kotlinx.collections.immutable) testImplementation(projects.features.enterprise.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushproviders.test) testImplementation(projects.libraries.pushstore.test) - testImplementation(projects.tests.testutils) testImplementation(projects.services.toolbox.test) testImplementation(projects.services.appnavstate.test) } diff --git a/libraries/pushstore/impl/build.gradle.kts b/libraries/pushstore/impl/build.gradle.kts index 659fb2f9ea..ea45836d1f 100644 --- a/libraries/pushstore/impl/build.gradle.kts +++ b/libraries/pushstore/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -31,12 +32,7 @@ dependencies { implementation(libs.androidx.corektx) implementation(libs.androidx.datastore.preferences) - testImplementation(libs.test.junit) - testImplementation(libs.test.mockk) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.coroutines.test) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.preferences.test) testImplementation(projects.services.appnavstate.test) diff --git a/libraries/roomselect/impl/build.gradle.kts b/libraries/roomselect/impl/build.gradle.kts index 5f9ebf7536..de0834e635 100644 --- a/libraries/roomselect/impl/build.gradle.kts +++ b/libraries/roomselect/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -28,11 +29,6 @@ dependencies { implementation(projects.libraries.uiStrings) api(projects.libraries.roomselect.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) } diff --git a/libraries/session-storage/impl/build.gradle.kts b/libraries/session-storage/impl/build.gradle.kts index 6e9f480b42..b9f96e1105 100644 --- a/libraries/session-storage/impl/build.gradle.kts +++ b/libraries/session-storage/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -28,12 +29,8 @@ dependencies { implementation(projects.libraries.di) implementation(libs.sqldelight.coroutines) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.coroutines.test) + testCommonDependencies(libs) testImplementation(libs.sqldelight.driver.jvm) - testImplementation(projects.tests.testutils) } sqldelight { diff --git a/libraries/textcomposer/impl/build.gradle.kts b/libraries/textcomposer/impl/build.gradle.kts index c7b4c15089..6f735bec23 100644 --- a/libraries/textcomposer/impl/build.gradle.kts +++ b/libraries/textcomposer/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -42,14 +43,6 @@ dependencies { debugApi(libs.matrix.richtexteditor.compose) } - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.robolectric) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/libraries/troubleshoot/impl/build.gradle.kts b/libraries/troubleshoot/impl/build.gradle.kts index 17514df8bf..bcc7c4357b 100644 --- a/libraries/troubleshoot/impl/build.gradle.kts +++ b/libraries/troubleshoot/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -33,16 +34,8 @@ dependencies { api(projects.libraries.push.api) implementation(projects.services.analytics.api) - testImplementation(libs.test.junit) - testImplementation(libs.test.robolectric) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) - testImplementation(libs.coroutines.test) + testCommonDependencies(libs, true) testImplementation(projects.services.analytics.test) - testImplementation(projects.tests.testutils) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.push.test) - testImplementation(libs.androidx.compose.ui.test.junit) - testReleaseImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/libraries/ui-utils/build.gradle.kts b/libraries/ui-utils/build.gradle.kts index 62962fbcb4..95ce3d21a1 100644 --- a/libraries/ui-utils/build.gradle.kts +++ b/libraries/ui-utils/build.gradle.kts @@ -1,3 +1,5 @@ +import extension.testCommonDependencies + /* * Copyright 2023, 2024 New Vector Ltd. * @@ -16,9 +18,6 @@ android { implementation(projects.libraries.androidutils) implementation(projects.services.toolbox.impl) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.truth) + testCommonDependencies(libs) } } diff --git a/libraries/usersearch/impl/build.gradle.kts b/libraries/usersearch/impl/build.gradle.kts index 6498c3a44e..c7378aa07a 100644 --- a/libraries/usersearch/impl/build.gradle.kts +++ b/libraries/usersearch/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -26,11 +27,7 @@ dependencies { api(projects.libraries.usersearch.api) implementation(libs.kotlinx.collections.immutable) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.usersearch.test) } diff --git a/libraries/voiceplayer/impl/build.gradle.kts b/libraries/voiceplayer/impl/build.gradle.kts index b512608a0d..053914d86b 100644 --- a/libraries/voiceplayer/impl/build.gradle.kts +++ b/libraries/voiceplayer/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2024 New Vector Ltd. @@ -30,15 +31,9 @@ dependencies { implementation(libs.androidx.annotationjvm) implementation(libs.coroutines.core) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.mockk) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(libs.coroutines.core) - testImplementation(libs.coroutines.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.mediaplayer.test) testImplementation(projects.services.analytics.test) - testImplementation(projects.tests.testutils) } diff --git a/libraries/voicerecorder/impl/build.gradle.kts b/libraries/voicerecorder/impl/build.gradle.kts index 7a4ed8c294..a09106a8c3 100644 --- a/libraries/voicerecorder/impl/build.gradle.kts +++ b/libraries/voicerecorder/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -28,11 +29,6 @@ dependencies { implementation(libs.androidx.annotationjvm) implementation(libs.coroutines.core) - testImplementation(projects.tests.testutils) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.mockk) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(libs.coroutines.core) - testImplementation(libs.coroutines.test) } diff --git a/libraries/wellknown/impl/build.gradle.kts b/libraries/wellknown/impl/build.gradle.kts index 1d7927da57..4de8ecc0fd 100644 --- a/libraries/wellknown/impl/build.gradle.kts +++ b/libraries/wellknown/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2025 New Vector Ltd. @@ -31,12 +32,8 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.network) - testImplementation(projects.tests.testutils) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) - testImplementation(libs.test.robolectric) + testCommonDependencies(libs) testImplementation(libs.coroutines.core) - testImplementation(libs.coroutines.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.toolbox.test) } diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index 53dcd8f16e..af87cffb99 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -20,6 +20,7 @@ import org.gradle.kotlin.dsl.project private fun DependencyHandlerScope.implementation(dependency: Any) = dependencies.add("implementation", dependency) private fun DependencyHandlerScope.testImplementation(dependency: Any) = dependencies.add("testImplementation", dependency) +private fun DependencyHandlerScope.testReleaseImplementation(dependency: Any) = dependencies.add("testReleaseImplementation", dependency) internal fun DependencyHandler.implementation(dependency: Any) = add("implementation", dependency) // Implementation + config block @@ -36,7 +37,10 @@ private fun DependencyHandlerScope.releaseImplementation(dependency: Any) = depe /** * Dependencies used for unit tests. */ -fun DependencyHandlerScope.testCommonDependencies(libs: LibrariesForLibs) { +fun DependencyHandlerScope.testCommonDependencies( + libs: LibrariesForLibs, + includeTestComposeView: Boolean = false, +) { testImplementation(libs.androidx.test.ext.junit) testImplementation(libs.coroutines.test) testImplementation(libs.molecule.runtime) @@ -46,6 +50,10 @@ fun DependencyHandlerScope.testCommonDependencies(libs: LibrariesForLibs) { testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(project(":tests:testutils")) + if (includeTestComposeView) { + testImplementation(libs.androidx.compose.ui.test.junit) + testReleaseImplementation(libs.androidx.compose.ui.test.manifest) + } } /** diff --git a/services/analytics/impl/build.gradle.kts b/services/analytics/impl/build.gradle.kts index 45b5d0a9f4..83eebead5d 100644 --- a/services/analytics/impl/build.gradle.kts +++ b/services/analytics/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -30,10 +31,7 @@ dependencies { api(projects.services.analytics.api) implementation(libs.androidx.datastore.preferences) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.junit) - testImplementation(libs.test.truth) + testCommonDependencies(libs) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.analyticsproviders.test) - testImplementation(projects.tests.testutils) } diff --git a/services/analyticsproviders/posthog/build.gradle.kts b/services/analyticsproviders/posthog/build.gradle.kts index b364552fb1..ffcb2ba590 100644 --- a/services/analyticsproviders/posthog/build.gradle.kts +++ b/services/analyticsproviders/posthog/build.gradle.kts @@ -1,6 +1,7 @@ import config.BuildTimeConfig import extension.buildConfigFieldStr import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -42,9 +43,5 @@ dependencies { implementation(projects.libraries.di) implementation(projects.services.analyticsproviders.api) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.truth) - testImplementation(libs.test.junit) - testImplementation(projects.tests.testutils) - testImplementation(libs.test.mockk) + testCommonDependencies(libs) } diff --git a/services/apperror/impl/build.gradle.kts b/services/apperror/impl/build.gradle.kts index 606c9a3d64..673468e99a 100644 --- a/services/apperror/impl/build.gradle.kts +++ b/services/apperror/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -29,9 +30,6 @@ dependencies { api(projects.services.apperror.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.turbine) - testImplementation(libs.test.truth) + testCommonDependencies(libs) testImplementation(projects.services.toolbox.test) } diff --git a/services/appnavstate/impl/build.gradle.kts b/services/appnavstate/impl/build.gradle.kts index 13a7cdfe1c..ba58e96f69 100644 --- a/services/appnavstate/impl/build.gradle.kts +++ b/services/appnavstate/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2022-2024 New Vector Ltd. @@ -28,10 +29,7 @@ dependencies { api(projects.services.appnavstate.api) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.test.truth) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) testImplementation(projects.services.appnavstate.test) } diff --git a/tools/templates/files/fileTemplates/Template Module Feature Build Gradle Impl.kts b/tools/templates/files/fileTemplates/Template Module Feature Build Gradle Impl.kts index 5ba8e9f684..d650a1f3e2 100644 --- a/tools/templates/files/fileTemplates/Template Module Feature Build Gradle Impl.kts +++ b/tools/templates/files/fileTemplates/Template Module Feature Build Gradle Impl.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies plugins { id("io.element.android-compose-library") @@ -19,10 +20,6 @@ dependencies { implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) } From a1aeb24f23de2fbfca2059f381e883f408a3e2a9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Sep 2025 21:32:24 +0200 Subject: [PATCH 065/145] Add test on DefaultEntryPoints --- .../android/appnav/di/RoomComponentFactory.kt | 2 +- .../analytics/api/AnalyticsEntryPoint.kt | 2 +- .../api/ChangeRoomMemberRolesEntryPoint.kt | 2 +- .../impl/ChangeRolesPresenter.kt | 2 +- .../impl/ChangeRolesPresenterTest.kt | 29 ++-- ...faultChangeRoomMemberRolesEntyPointTest.kt | 44 ++++++ .../impl/DefaultCreateRoomEntryPointTest.kt | 40 +++++ .../impl/AccountDeactivationPresenterTest.kt | 11 +- ...efaultAccountDeactivationEntryPointTest.kt | 32 ++++ .../ftue/impl/DefaultFtueEntryPointTest.kt | 54 +++++++ .../ftue/impl/DefaultFtueServiceTest.kt | 36 ++--- .../home/impl/DefaultHomeEntryPointTest.kt | 59 +++++++ .../features/home/impl/HomePresenterTest.kt | 40 ++--- .../acceptdecline/AcceptDeclineInviteView.kt | 2 +- .../DeclineInviteAndBlockEntryPoint.kt | 2 +- .../DeclineAndBlockPresenter.kt | 2 +- .../DeclineAndBlockPresenterTest.kt | 37 ++--- .../DefaultDeclineAndBlockEntryPointTest.kt | 39 +++++ .../joinroom/impl/JoinRoomPresenter.kt | 2 +- .../impl/DefaultJoinRoomEntryPointTest.kt | 54 +++++++ .../joinroom/impl/JoinRoomPresenterTest.kt | 66 ++++---- .../DefaultKnockRequestsListEntryPointTest.kt | 34 ++++ .../list/KnockRequestsListPresenterTest.kt | 30 ++-- .../leaveroom/api/LeaveRoomRenderer.kt | 2 +- ...efaultOpenSourcesLicensesEntryPointTest.kt | 31 ++++ .../permissions/PermissionsPresenter.kt | 2 +- .../impl/send/SendLocationPresenter.kt | 2 +- .../location/impl/show/ShowLocationNode.kt | 4 +- .../impl/show/ShowLocationPresenter.kt | 6 +- .../send/DefaultSendLocationEntryPointTest.kt | 53 +++++++ .../show/DefaultShowLocationEntryPointTest.kt | 56 +++++++ .../impl/show/ShowLocationPresenterTest.kt | 8 +- .../location/test/FakeLocationService.kt | 2 +- .../impl/DefaultLockScreenEntryPointTest.kt | 62 ++++++++ .../login/impl/DefaultLoginEntryPointTest.kt | 50 ++++++ .../logout/api/direct/DirectLogoutView.kt | 2 +- .../impl/DefaultLogoutEntryPointTest.kt | 41 +++++ .../logout/impl/LogoutPresenterTest.kt | 16 +- .../impl/DefaultMessagesEntryPointTest.kt | 121 +++++++++++++++ .../PinnedMessagesBannerPresenterTest.kt | 12 +- .../impl/timeline/TimelineControllerTest.kt | 10 ++ .../poll/impl/create/CreatePollPresenter.kt | 2 +- .../features/poll/impl/data/PollRepository.kt | 2 +- .../create/DefaultCreatePollEntryPointTest.kt | 60 ++++++++ .../DefaultPollHistoryEntryPointTest.kt | 38 +++++ .../impl/history/PollHistoryPresenterTest.kt | 38 ++--- .../impl/DefaultPreferencesEntryPointTest.kt | 77 ++++++++++ .../impl/bugreport/BugReportPresenterTest.kt | 22 +-- .../DefaultBugReportEntryPointTest.kt | 43 ++++++ .../reportroom/api/ReportRoomEntryPoint.kt | 2 +- .../reportroom/impl/ReportRoomPresenter.kt | 2 +- .../impl/DefaultReportRoomEntryPointTest.kt | 37 +++++ .../impl/ReportRoomPresenterTest.kt | 14 +- .../impl/RoomAliasResolverPresenter.kt | 2 +- .../DefaultRoomAliasResolverEntryPointTest.kt | 53 +++++++ .../impl/RoomAliasHelperPresenterTest.kt | 16 +- .../impl/DefaultRoomDetailsEntryPointTest.kt | 105 +++++++++++++ .../DefaultRoomDirectoryEntryPointTest.kt | 44 ++++++ .../impl/root/RoomDirectoryPresenterTest.kt | 22 +-- .../impl/DefaultSecureBackupEntryPointTest.kt | 42 +++++ .../features/share/impl/SharePresenter.kt | 2 +- .../share/impl/DefaultShareEntryPointTest.kt | 55 +++++++ .../features/share/impl/SharePresenterTest.kt | 38 ++--- .../signedout/impl/SignedOutPresenter.kt | 2 +- .../impl/DefaultSignedOutEntryPointTest.kt | 41 +++++ .../signedout/impl/SignedOutPresenterTest.kt | 26 ++-- .../space/impl/DefaultSpaceEntryPointTest.kt | 2 +- .../impl/DefaultStartChatEntryPointTest.kt | 47 ++++++ .../impl/root/StartChatPresenterTest.kt | 38 ++--- .../impl/DefaultUserProfileEntryPointTest.kt | 79 ++++++++++ .../incoming/IncomingVerificationPresenter.kt | 2 +- .../outgoing/OutgoingVerificationPresenter.kt | 2 +- ...faultIncomingVerificationEntryPointTest.kt | 46 ++++++ .../IncomingVerificationPresenterTest.kt | 54 +++---- ...faultOutgoingVerificationEntryPointTest.kt | 51 ++++++ .../OutgoingVerificationPresenterTest.kt | 28 ++-- .../impl/DefaultViewFolderEntryPointTest.kt | 45 ++++++ .../architecture/FeatureEntryPoint.kt | 2 +- .../api/usecase/InviteFriendsUseCase.kt | 2 +- libraries/mediaviewer/impl/build.gradle.kts | 1 + ...edTimelineMediaGalleryDataSourceFactory.kt | 2 +- .../impl/viewer/MediaViewerPresenter.kt | 2 +- .../impl/DefaultMediaGalleryEntryPointTest.kt | 47 ++++++ .../impl/DefaultMediaViewerEntryPointTest.kt | 145 ++++++++++++++++++ .../TimelineMediaGalleryDataSourceTest.kt | 24 +-- .../impl/viewer/MediaViewerPresenterTest.kt | 133 ++++++++++------ .../SingleMediaGalleryDataSourceTest.kt | 2 +- .../roomselect/impl/RoomSelectPresenter.kt | 2 +- .../impl/DefaultRoomSelectEntryPointTest.kt | 51 ++++++ .../impl/RoomSelectPresenterTest.kt | 22 +-- ...tNotificationTroubleShootEntryPointTest.kt | 42 +++++ .../TroubleshootNotificationsPresenterTest.kt | 38 ++--- .../DefaultPushHistoryEntryPointTest.kt | 49 ++++++ 93 files changed, 2426 insertions(+), 418 deletions(-) create mode 100644 features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/DefaultChangeRoomMemberRolesEntyPointTest.kt create mode 100644 features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt create mode 100644 features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt create mode 100644 features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt create mode 100644 features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt create mode 100644 features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt create mode 100644 features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt create mode 100644 features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt create mode 100644 features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt create mode 100644 features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt create mode 100644 features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt create mode 100644 features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt create mode 100644 features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt create mode 100644 features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt create mode 100644 features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt create mode 100644 features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt create mode 100644 features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt create mode 100644 features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt create mode 100644 features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt create mode 100644 features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt create mode 100644 features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt create mode 100644 features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt create mode 100644 features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt create mode 100644 features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt create mode 100644 features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt create mode 100644 features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt create mode 100644 features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt create mode 100644 features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt create mode 100644 libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt create mode 100644 libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt create mode 100644 libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt create mode 100644 libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt create mode 100644 libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt diff --git a/appnav/src/main/kotlin/io/element/android/appnav/di/RoomComponentFactory.kt b/appnav/src/main/kotlin/io/element/android/appnav/di/RoomComponentFactory.kt index 4911ab50b5..fc8f2c175b 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/di/RoomComponentFactory.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/di/RoomComponentFactory.kt @@ -9,6 +9,6 @@ package io.element.android.appnav.di import io.element.android.libraries.matrix.api.room.JoinedRoom -interface RoomComponentFactory { +fun interface RoomComponentFactory { fun create(room: JoinedRoom): Any } diff --git a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/AnalyticsEntryPoint.kt b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/AnalyticsEntryPoint.kt index 404bae44d1..37a78fd727 100644 --- a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/AnalyticsEntryPoint.kt +++ b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/AnalyticsEntryPoint.kt @@ -9,4 +9,4 @@ package io.element.android.features.analytics.api import io.element.android.libraries.architecture.SimpleFeatureEntryPoint -interface AnalyticsEntryPoint : SimpleFeatureEntryPoint +fun interface AnalyticsEntryPoint : SimpleFeatureEntryPoint diff --git a/features/changeroommemberroles/api/src/main/kotlin/io/element/android/features/changeroommemberroes/api/ChangeRoomMemberRolesEntryPoint.kt b/features/changeroommemberroles/api/src/main/kotlin/io/element/android/features/changeroommemberroes/api/ChangeRoomMemberRolesEntryPoint.kt index 0175cdf247..b6f7680b38 100644 --- a/features/changeroommemberroles/api/src/main/kotlin/io/element/android/features/changeroommemberroes/api/ChangeRoomMemberRolesEntryPoint.kt +++ b/features/changeroommemberroles/api/src/main/kotlin/io/element/android/features/changeroommemberroes/api/ChangeRoomMemberRolesEntryPoint.kt @@ -14,7 +14,7 @@ import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.JoinedRoom -interface ChangeRoomMemberRolesEntryPoint : FeatureEntryPoint { +fun interface ChangeRoomMemberRolesEntryPoint : FeatureEntryPoint { fun builder(parentNode: Node, buildContext: BuildContext): Builder interface Builder { diff --git a/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenter.kt b/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenter.kt index a6d0ed6a51..cf43874b10 100644 --- a/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenter.kt +++ b/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenter.kt @@ -55,7 +55,7 @@ class ChangeRolesPresenter( private val analyticsService: AnalyticsService, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(role: RoomMember.Role): ChangeRolesPresenter } diff --git a/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenterTest.kt b/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenterTest.kt index a5b2da566c..e5e22b8846 100644 --- a/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenterTest.kt +++ b/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenterTest.kt @@ -37,7 +37,6 @@ import kotlinx.collections.immutable.toPersistentMap import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test -import kotlin.collections.plus class ChangeRolesPresenterTest { @Test @@ -556,18 +555,18 @@ class ChangeRolesPresenterTest { users = pairs.associate { (userId, role) -> userId to role.powerLevel }.toPersistentMap() ) } - - private fun TestScope.createChangeRolesPresenter( - role: RoomMember.Role = RoomMember.Role.Admin, - room: FakeJoinedRoom = FakeJoinedRoom(baseRoom = FakeBaseRoom(updateMembersResult = {})), - dispatchers: CoroutineDispatchers = testCoroutineDispatchers(), - analyticsService: FakeAnalyticsService = FakeAnalyticsService(), - ): ChangeRolesPresenter { - return ChangeRolesPresenter( - role = role, - room = room, - dispatchers = dispatchers, - analyticsService = analyticsService, - ) - } +} + +internal fun TestScope.createChangeRolesPresenter( + role: RoomMember.Role = RoomMember.Role.Admin, + room: FakeJoinedRoom = FakeJoinedRoom(baseRoom = FakeBaseRoom(updateMembersResult = {})), + dispatchers: CoroutineDispatchers = testCoroutineDispatchers(), + analyticsService: FakeAnalyticsService = FakeAnalyticsService(), +): ChangeRolesPresenter { + return ChangeRolesPresenter( + role = role, + room = room, + dispatchers = dispatchers, + analyticsService = analyticsService, + ) } diff --git a/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/DefaultChangeRoomMemberRolesEntyPointTest.kt b/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/DefaultChangeRoomMemberRolesEntyPointTest.kt new file mode 100644 index 0000000000..5f68fe5970 --- /dev/null +++ b/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/DefaultChangeRoomMemberRolesEntyPointTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.changeroommemberroles.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.changeroommemberroes.api.ChangeRoomMemberRolesListType +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultChangeRoomMemberRolesEntyPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultChangeRoomMemberRolesEntyPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ChangeRoomMemberRolesRootNode( + buildContext = buildContext, + plugins = plugins, + roomComponentFactory = { }, + ) + } + val room = FakeJoinedRoom() + val listType = ChangeRoomMemberRolesListType.Admins + val result = entryPoint.builder(parentNode, BuildContext.root(null)) + .room(FakeJoinedRoom()) + .listType(listType) + .build() + assertThat(result).isInstanceOf(ChangeRoomMemberRolesRootNode::class.java) + // Search for the Inputs plugin + val input = result.plugins.filterIsInstance().single() + assertThat(input.joinedRoom.roomId).isEqualTo(room.roomId) + assertThat(input.listType).isEqualTo(listType) + } +} diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt new file mode 100644 index 0000000000..6c6790adff --- /dev/null +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.createroom.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.createroom.api.CreateRoomEntryPoint +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultCreateRoomEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultCreateRoomEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + CreateRoomFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val callback = object : CreateRoomEntryPoint.Callback { + override fun onRoomCreated(roomId: RoomId) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt index 1383bdde21..e8edea3ab6 100644 --- a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt @@ -149,9 +149,10 @@ class AccountDeactivationPresenterTest { } } - private fun createPresenter( - matrixClient: MatrixClient = FakeMatrixClient(), - ) = AccountDeactivationPresenter( - matrixClient = matrixClient, - ) } + +internal fun createPresenter( + matrixClient: MatrixClient = FakeMatrixClient(), +) = AccountDeactivationPresenter( + matrixClient = matrixClient, +) diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt new file mode 100644 index 0000000000..e055b4a979 --- /dev/null +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultAccountDeactivationEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultAccountDeactivationEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + AccountDeactivationNode( + buildContext = buildContext, + plugins = plugins, + presenter = createPresenter(), + ) + } + val result = entryPoint.createNode(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(AccountDeactivationNode::class.java) + } +} diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt new file mode 100644 index 0000000000..3a4a2ea334 --- /dev/null +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.ftue.impl + +import android.content.Context +import android.content.Intent +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.lockscreen.api.LockScreenEntryPoint +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultFtueEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultFtueEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + FtueFlowNode( + buildContext = buildContext, + plugins = plugins, + analyticsEntryPoint = { _, _ -> lambdaError() }, + ftueState = createDefaultFtueService(), + analyticsService = FakeAnalyticsService(), + lockScreenEntryPoint = object : LockScreenEntryPoint { + override fun nodeBuilder( + parentNode: com.bumble.appyx.core.node.Node, + buildContext: BuildContext, + navTarget: LockScreenEntryPoint.Target + ): LockScreenEntryPoint.NodeBuilder { + lambdaError() + } + + override fun pinUnlockIntent(context: Context): Intent { + lambdaError() + } + }, + ) + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .build() + assertThat(result).isInstanceOf(FtueFlowNode::class.java) + } +} diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt index 4a05433e5e..1a4a8738dc 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt @@ -226,22 +226,22 @@ class DefaultFtueServiceTest { resetPermissionLambda.assertions().isCalledOnce() .with(value("android.permission.POST_NOTIFICATIONS")) } - - private fun TestScope.createDefaultFtueService( - sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(), - analyticsService: AnalyticsService = FakeAnalyticsService(), - permissionStateProvider: PermissionStateProvider = FakePermissionStateProvider(permissionGranted = false), - lockScreenService: LockScreenService = FakeLockScreenService(), - sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), - // First version where notification permission is required - sdkIntVersion: Int = Build.VERSION_CODES.TIRAMISU, - ) = DefaultFtueService( - sessionCoroutineScope = backgroundScope, - sessionVerificationService = sessionVerificationService, - sdkVersionProvider = FakeBuildVersionSdkIntProvider(sdkIntVersion), - analyticsService = analyticsService, - permissionStateProvider = permissionStateProvider, - lockScreenService = lockScreenService, - sessionPreferencesStore = sessionPreferencesStore, - ) } + +internal fun TestScope.createDefaultFtueService( + sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(), + analyticsService: AnalyticsService = FakeAnalyticsService(), + permissionStateProvider: PermissionStateProvider = FakePermissionStateProvider(permissionGranted = false), + lockScreenService: LockScreenService = FakeLockScreenService(), + sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), + // First version where notification permission is required + sdkIntVersion: Int = Build.VERSION_CODES.TIRAMISU, +) = DefaultFtueService( + sessionCoroutineScope = backgroundScope, + sessionVerificationService = sessionVerificationService, + sdkVersionProvider = FakeBuildVersionSdkIntProvider(sdkIntVersion), + analyticsService = analyticsService, + permissionStateProvider = permissionStateProvider, + lockScreenService = lockScreenService, + sessionPreferencesStore = sessionPreferencesStore, +) diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt new file mode 100644 index 0000000000..0eacd792c7 --- /dev/null +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.home.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.home.api.HomeEntryPoint +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultHomeEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultHomeEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + HomeFlowNode( + buildContext = buildContext, + plugins = plugins, + matrixClient = FakeMatrixClient(), + presenter = createHomePresenter(), + inviteFriendsUseCase = { lambdaError() }, + analyticsService = FakeAnalyticsService(), + acceptDeclineInviteView = { _, _, _, _ -> lambdaError() }, + directLogoutView = { _ -> lambdaError() }, + reportRoomEntryPoint = { _, _, _ -> lambdaError() }, + declineInviteAndBlockUserEntryPoint = { _, _, _ -> lambdaError() }, + changeRoomMemberRolesEntryPoint = { _, _ -> lambdaError() }, + leaveRoomRenderer = { _, _, _ -> lambdaError() }, + ) + } + val callback = object : HomeEntryPoint.Callback { + override fun onRoomClick(roomId: RoomId) = lambdaError() + override fun onStartChatClick() = lambdaError() + override fun onSettingsClick() = lambdaError() + override fun onSetUpRecoveryClick() = lambdaError() + override fun onSessionConfirmRecoveryKeyClick() = lambdaError() + override fun onRoomSettingsClick(roomId: RoomId) = lambdaError() + override fun onReportBugClick() = lambdaError() + override fun onLogoutForNativeSlidingSyncMigrationNeeded() = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(HomeFlowNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt index 57f270d3d3..a84dbd6309 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt @@ -175,24 +175,24 @@ class HomePresenterTest { assertThat(finalState.showNavigationBar).isFalse() } } - - private fun createHomePresenter( - client: MatrixClient = FakeMatrixClient(), - syncService: SyncService = FakeSyncService(), - snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(), - rageshakeFeatureAvailability: RageshakeFeatureAvailability = RageshakeFeatureAvailability { flowOf(false) }, - indicatorService: IndicatorService = FakeIndicatorService(), - featureFlagService: FeatureFlagService = FakeFeatureFlagService(), - homeSpacesPresenter: Presenter = Presenter { aHomeSpacesState() }, - ) = HomePresenter( - client = client, - syncService = syncService, - snackbarDispatcher = snackbarDispatcher, - indicatorService = indicatorService, - logoutPresenter = { aDirectLogoutState() }, - roomListPresenter = { aRoomListState() }, - homeSpacesPresenter = homeSpacesPresenter, - rageshakeFeatureAvailability = rageshakeFeatureAvailability, - featureFlagService = featureFlagService, - ) } + +internal fun createHomePresenter( + client: MatrixClient = FakeMatrixClient(), + syncService: SyncService = FakeSyncService(), + snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(), + rageshakeFeatureAvailability: RageshakeFeatureAvailability = RageshakeFeatureAvailability { flowOf(false) }, + indicatorService: IndicatorService = FakeIndicatorService(), + featureFlagService: FeatureFlagService = FakeFeatureFlagService(), + homeSpacesPresenter: Presenter = Presenter { aHomeSpacesState() }, +) = HomePresenter( + client = client, + syncService = syncService, + snackbarDispatcher = snackbarDispatcher, + indicatorService = indicatorService, + logoutPresenter = { aDirectLogoutState() }, + roomListPresenter = { aRoomListState() }, + homeSpacesPresenter = homeSpacesPresenter, + rageshakeFeatureAvailability = rageshakeFeatureAvailability, + featureFlagService = featureFlagService, +) diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/acceptdecline/AcceptDeclineInviteView.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/acceptdecline/AcceptDeclineInviteView.kt index 78be5ebd16..a098443c45 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/acceptdecline/AcceptDeclineInviteView.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/acceptdecline/AcceptDeclineInviteView.kt @@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import io.element.android.libraries.matrix.api.core.RoomId -interface AcceptDeclineInviteView { +fun interface AcceptDeclineInviteView { @Composable fun Render( state: AcceptDeclineInviteState, diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/declineandblock/DeclineInviteAndBlockEntryPoint.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/declineandblock/DeclineInviteAndBlockEntryPoint.kt index 27080ee354..8517fe2786 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/declineandblock/DeclineInviteAndBlockEntryPoint.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/declineandblock/DeclineInviteAndBlockEntryPoint.kt @@ -12,6 +12,6 @@ import com.bumble.appyx.core.node.Node import io.element.android.features.invite.api.InviteData import io.element.android.libraries.architecture.FeatureEntryPoint -interface DeclineInviteAndBlockEntryPoint : FeatureEntryPoint { +fun interface DeclineInviteAndBlockEntryPoint : FeatureEntryPoint { fun createNode(parentNode: Node, buildContext: BuildContext, inviteData: InviteData): Node } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenter.kt index 527a467ba9..f9639f69fe 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenter.kt @@ -35,7 +35,7 @@ class DeclineAndBlockPresenter( private val snackbarDispatcher: SnackbarDispatcher, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(inviteData: InviteData): DeclineAndBlockPresenter } diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt index c5d2f53c92..ae8893f829 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt @@ -11,6 +11,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.invite.api.InviteData import io.element.android.features.invite.impl.DeclineInvite import io.element.android.features.invite.impl.fake.FakeDeclineInvite +import io.element.android.features.invite.test.anInviteData import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.matrix.api.core.RoomId @@ -148,28 +149,16 @@ class DeclineAndBlockPresenterTest { .isCalledOnce() .with(value(A_ROOM_ID), value(true), value(false), value("")) } - - private fun anInviteData( - roomId: RoomId = A_ROOM_ID, - name: String = A_ROOM_NAME, - isDm: Boolean = false, - ): InviteData { - return InviteData( - roomId = roomId, - roomName = name, - isDm = isDm, - ) - } - - private fun createDeclineAndBlockPresenter( - inviteData: InviteData = anInviteData(), - declineInvite: DeclineInvite = FakeDeclineInvite(), - snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(), - ): DeclineAndBlockPresenter { - return DeclineAndBlockPresenter( - inviteData = inviteData, - declineInvite = declineInvite, - snackbarDispatcher = snackbarDispatcher, - ) - } +} + +internal fun createDeclineAndBlockPresenter( + inviteData: InviteData = anInviteData(), + declineInvite: DeclineInvite = FakeDeclineInvite(), + snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(), +): DeclineAndBlockPresenter { + return DeclineAndBlockPresenter( + inviteData = inviteData, + declineInvite = declineInvite, + snackbarDispatcher = snackbarDispatcher, + ) } diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt new file mode 100644 index 0000000000..a3016a785c --- /dev/null +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.invite.impl.declineandblock + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.invite.test.anInviteData +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultDeclineAndBlockEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultDeclineAndBlockEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + DeclineAndBlockNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { inviteData -> createDeclineAndBlockPresenter() } + ) + } + val inviteData = anInviteData() + val result = entryPoint.createNode( + parentNode = parentNode, + buildContext = BuildContext.root(null), + inviteData = inviteData + ) + assertThat(result).isInstanceOf(DeclineAndBlockNode::class.java) + assertThat(result.plugins).contains(DeclineAndBlockNode.Inputs(inviteData)) + } +} 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 5fe12a42d9..3200d75f78 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 @@ -70,7 +70,7 @@ class JoinRoomPresenter( private val buildMeta: BuildMeta, private val seenInvitesStore: SeenInvitesStore, ) : Presenter { - interface Factory { + fun interface Factory { fun create( roomId: RoomId, roomIdOrAlias: RoomIdOrAlias, diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt new file mode 100644 index 0000000000..aa81b0c51b --- /dev/null +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.joinroom.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import im.vector.app.features.analytics.plan.JoinedRoom +import io.element.android.features.invite.api.InviteData +import io.element.android.features.invite.api.declineandblock.DeclineInviteAndBlockEntryPoint +import io.element.android.features.joinroom.api.JoinRoomEntryPoint +import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith +import java.util.Optional + +@RunWith(AndroidJUnit4::class) +class DefaultJoinRoomEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultJoinRoomEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + JoinRoomFlowNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { _, _, _, _, _ -> createJoinRoomPresenter() }, + acceptDeclineInviteView = { _, _, _, _ -> lambdaError() }, + declineAndBlockEntryPoint = object : DeclineInviteAndBlockEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext, inviteData: InviteData) = lambdaError() + } + + ) + } + val inputs = JoinRoomEntryPoint.Inputs( + roomId = A_ROOM_ID, + roomIdOrAlias = A_ROOM_ID.toRoomIdOrAlias(), + roomDescription = Optional.ofNullable(null), + serverNames = emptyList(), + trigger = JoinedRoom.Trigger.RoomDirectory, + ) + val result = entryPoint.createNode(parentNode, BuildContext.root(null), inputs) + assertThat(result).isInstanceOf(JoinRoomFlowNode::class.java) + assertThat(result.plugins).contains(inputs) + } +} 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 cabab56802..a06a80ab58 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 @@ -1042,39 +1042,6 @@ class JoinRoomPresenterTest { } } - private fun createJoinRoomPresenter( - roomId: RoomId = A_ROOM_ID, - roomDescription: Optional = Optional.empty(), - serverNames: List = emptyList(), - trigger: JoinedRoom.Trigger = JoinedRoom.Trigger.Invite, - matrixClient: MatrixClient = FakeMatrixClient(), - joinRoomLambda: (RoomIdOrAlias, List, JoinedRoom.Trigger) -> Result = { _, _, _ -> - Result.success(Unit) - }, - knockRoom: KnockRoom = FakeKnockRoom(), - cancelKnockRoom: CancelKnockRoom = FakeCancelKnockRoom(), - forgetRoom: ForgetRoom = FakeForgetRoom(), - buildMeta: BuildMeta = aBuildMeta(applicationName = "AppName"), - acceptDeclineInvitePresenter: Presenter = Presenter { anAcceptDeclineInviteState() }, - seenInvitesStore: SeenInvitesStore = InMemorySeenInvitesStore(), - ): JoinRoomPresenter { - return JoinRoomPresenter( - roomId = roomId, - roomIdOrAlias = roomId.toRoomIdOrAlias(), - roomDescription = roomDescription, - serverNames = serverNames, - trigger = trigger, - matrixClient = matrixClient, - joinRoom = FakeJoinRoom(joinRoomLambda), - knockRoom = knockRoom, - cancelKnockRoom = cancelKnockRoom, - forgetRoom = forgetRoom, - buildMeta = buildMeta, - acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, - seenInvitesStore = seenInvitesStore, - ) - } - private fun aRoomDescription( roomId: RoomId = A_ROOM_ID, name: String? = A_ROOM_NAME, @@ -1095,3 +1062,36 @@ class JoinRoomPresenterTest { ) } } + +internal fun createJoinRoomPresenter( + roomId: RoomId = A_ROOM_ID, + roomDescription: Optional = Optional.empty(), + serverNames: List = emptyList(), + trigger: JoinedRoom.Trigger = JoinedRoom.Trigger.Invite, + matrixClient: MatrixClient = FakeMatrixClient(), + joinRoomLambda: (RoomIdOrAlias, List, JoinedRoom.Trigger) -> Result = { _, _, _ -> + Result.success(Unit) + }, + knockRoom: KnockRoom = FakeKnockRoom(), + cancelKnockRoom: CancelKnockRoom = FakeCancelKnockRoom(), + forgetRoom: ForgetRoom = FakeForgetRoom(), + buildMeta: BuildMeta = aBuildMeta(applicationName = "AppName"), + acceptDeclineInvitePresenter: Presenter = Presenter { anAcceptDeclineInviteState() }, + seenInvitesStore: SeenInvitesStore = InMemorySeenInvitesStore(), +): JoinRoomPresenter { + return JoinRoomPresenter( + roomId = roomId, + roomIdOrAlias = roomId.toRoomIdOrAlias(), + roomDescription = roomDescription, + serverNames = serverNames, + trigger = trigger, + matrixClient = matrixClient, + joinRoom = FakeJoinRoom(joinRoomLambda), + knockRoom = knockRoom, + cancelKnockRoom = cancelKnockRoom, + forgetRoom = forgetRoom, + buildMeta = buildMeta, + acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, + seenInvitesStore = seenInvitesStore, + ) +} diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt new file mode 100644 index 0000000000..2a4196da9b --- /dev/null +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.knockrequests.impl.list + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultKnockRequestsListEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultKnockRequestsListEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + KnockRequestsListNode( + buildContext = buildContext, + plugins = plugins, + presenter = createKnockRequestsListPresenter(), + ) + } + val result = entryPoint.createNode(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(KnockRequestsListNode::class.java) + } +} diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt index 2d33642a06..18269e06f3 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt @@ -286,19 +286,19 @@ class KnockRequestsListPresenterTest { assert(acceptFailureLambda).isCalledOnce() assert(acceptSuccessLambda).isCalledOnce() } - - private fun TestScope.createKnockRequestsListPresenter( - canAccept: Boolean = true, - canDecline: Boolean = true, - canBan: Boolean = true, - knockRequestsFlow: Flow> = flowOf(emptyList()) - ): KnockRequestsListPresenter { - val knockRequestsService = KnockRequestsService( - knockRequestsFlow = knockRequestsFlow, - coroutineScope = backgroundScope, - isKnockFeatureEnabledFlow = flowOf(true), - permissionsFlow = flowOf(KnockRequestPermissions(canAccept, canDecline, canBan)), - ) - return KnockRequestsListPresenter(knockRequestsService = knockRequestsService) - } +} + +internal fun TestScope.createKnockRequestsListPresenter( + canAccept: Boolean = true, + canDecline: Boolean = true, + canBan: Boolean = true, + knockRequestsFlow: Flow> = flowOf(emptyList()) +): KnockRequestsListPresenter { + val knockRequestsService = KnockRequestsService( + knockRequestsFlow = knockRequestsFlow, + coroutineScope = backgroundScope, + isKnockFeatureEnabledFlow = flowOf(true), + permissionsFlow = flowOf(KnockRequestPermissions(canAccept, canDecline, canBan)), + ) + return KnockRequestsListPresenter(knockRequestsService = knockRequestsService) } diff --git a/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomRenderer.kt b/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomRenderer.kt index 8bd6fe830b..80252a83a6 100644 --- a/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomRenderer.kt +++ b/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomRenderer.kt @@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import io.element.android.libraries.matrix.api.core.RoomId -interface LeaveRoomRenderer { +fun interface LeaveRoomRenderer { @Composable fun Render( state: LeaveRoomState, diff --git a/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt b/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt new file mode 100644 index 0000000000..730760cb93 --- /dev/null +++ b/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.licenses.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultOpenSourcesLicensesEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultOpenSourcesLicensesEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + DependenciesFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val result = entryPoint.getNode(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(DependenciesFlowNode::class.java) + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenter.kt index 410214ec88..82e54ba977 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenter.kt @@ -10,7 +10,7 @@ package io.element.android.features.location.impl.common.permissions import io.element.android.libraries.architecture.Presenter interface PermissionsPresenter : Presenter { - interface Factory { + fun interface Factory { fun create(permissions: List): PermissionsPresenter } } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt index 15f858ecff..f8d78b96e2 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt @@ -47,7 +47,7 @@ class SendLocationPresenter( private val buildMeta: BuildMeta, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(timelineMode: Timeline.Mode): SendLocationPresenter } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationNode.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationNode.kt index 053f1864de..c0a6c5b6ad 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationNode.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationNode.kt @@ -25,10 +25,10 @@ import io.element.android.services.analytics.api.AnalyticsService @ContributesNode(RoomScope::class) @Inject class ShowLocationNode( - presenterFactory: ShowLocationPresenter.Factory, - analyticsService: AnalyticsService, @Assisted buildContext: BuildContext, @Assisted plugins: List, + presenterFactory: ShowLocationPresenter.Factory, + analyticsService: AnalyticsService, ) : Node(buildContext, plugins = plugins) { init { lifecycle.subscribe( diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt index af89331c6f..b304505367 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt @@ -28,14 +28,14 @@ import io.element.android.libraries.core.meta.BuildMeta @Inject class ShowLocationPresenter( + @Assisted private val location: Location, + @Assisted private val description: String?, permissionsPresenterFactory: PermissionsPresenter.Factory, private val locationActions: LocationActions, private val buildMeta: BuildMeta, - @Assisted private val location: Location, - @Assisted private val description: String? ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(location: Location, description: String?): ShowLocationPresenter } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt new file mode 100644 index 0000000000..705d2a293c --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.send + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.impl.common.actions.FakeLocationActions +import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter +import io.element.android.features.messages.test.FakeMessageComposerContext +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultSendLocationEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultSendLocationEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + SendLocationNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { timelineMode: Timeline.Mode -> + SendLocationPresenter( + permissionsPresenterFactory = { FakePermissionsPresenter() }, + room = FakeJoinedRoom(), + timelineMode = timelineMode, + analyticsService = FakeAnalyticsService(), + messageComposerContext = FakeMessageComposerContext(), + locationActions = FakeLocationActions(), + buildMeta = aBuildMeta(), + ) + }, + analyticsService = FakeAnalyticsService(), + ) + } + val timelineMode = Timeline.Mode.Live + val result = entryPoint.builder(timelineMode) + .build(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(SendLocationNode::class.java) + assertThat(result.plugins).contains(SendLocationNode.Inputs(timelineMode)) + } +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt new file mode 100644 index 0000000000..046f286550 --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.show + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.api.Location +import io.element.android.features.location.api.ShowLocationEntryPoint +import io.element.android.features.location.impl.common.actions.FakeLocationActions +import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter +import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultShowLocationEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultShowLocationEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ShowLocationNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { location: Location, description: String? -> + ShowLocationPresenter( + permissionsPresenterFactory = { FakePermissionsPresenter() }, + locationActions = FakeLocationActions(), + buildMeta = aBuildMeta(), + location = location, + description = description, + ) + }, + analyticsService = FakeAnalyticsService(), + ) + } + val inputs = ShowLocationEntryPoint.Inputs( + location = Location(37.4219983, -122.084, 10f), + description = "My location", + ) + val result = entryPoint.createNode( + parentNode, + BuildContext.root(null), + inputs = inputs, + ) + assertThat(result).isInstanceOf(ShowLocationNode::class.java) + assertThat(result.plugins).contains(inputs) + } +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt index 937d1d475e..cc53badbb2 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt @@ -37,10 +37,10 @@ class ShowLocationPresenterTest { permissionsPresenterFactory = object : PermissionsPresenter.Factory { override fun create(permissions: List): PermissionsPresenter = fakePermissionsPresenter }, - fakeLocationActions, - fakeBuildMeta, - location, - A_DESCRIPTION, + locationActions = fakeLocationActions, + buildMeta = fakeBuildMeta, + location = location, + description = A_DESCRIPTION, ) @Test diff --git a/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeLocationService.kt b/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeLocationService.kt index 8ba29a65aa..69a3331ffb 100644 --- a/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeLocationService.kt +++ b/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeLocationService.kt @@ -10,7 +10,7 @@ package io.element.android.features.location.test import io.element.android.features.location.api.LocationService class FakeLocationService( - private val isServiceAvailable: Boolean, + private val isServiceAvailable: Boolean = false, ) : LocationService { override fun isServiceAvailable() = isServiceAvailable } diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt new file mode 100644 index 0000000000..854e89b13a --- /dev/null +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.lockscreen.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.lockscreen.api.LockScreenEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultLockScreenEntryPointTest { + @Test + fun `test node builder Setup`() { + val entryPoint = DefaultLockScreenEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + LockScreenFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val callback = object : LockScreenEntryPoint.Callback { + override fun onSetupDone() = lambdaError() + } + val navTarget = LockScreenEntryPoint.Target.Setup + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null), navTarget) + .callback(callback) + .build() + assertThat(result).isInstanceOf(LockScreenFlowNode::class.java) + assertThat(result.plugins).contains(LockScreenFlowNode.Inputs(LockScreenFlowNode.NavTarget.Setup)) + assertThat(result.plugins).contains(callback) + } + + @Test + fun `test node builder Settings`() { + val entryPoint = DefaultLockScreenEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + LockScreenFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val callback = object : LockScreenEntryPoint.Callback { + override fun onSetupDone() = lambdaError() + } + val navTarget = LockScreenEntryPoint.Target.Settings + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null), navTarget) + .callback(callback) + .build() + assertThat(result).isInstanceOf(LockScreenFlowNode::class.java) + assertThat(result.plugins).contains(LockScreenFlowNode.Inputs(LockScreenFlowNode.NavTarget.Settings)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt new file mode 100644 index 0000000000..6b44f836b6 --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.login.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService +import io.element.android.features.login.api.LoginEntryPoint +import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource +import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultLoginEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultLoginEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + LoginFlowNode( + buildContext = buildContext, + plugins = plugins, + accountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), + oidcActionFlow = FakeOidcActionFlow(), + ) + } + val callback = object : LoginEntryPoint.Callback { + override fun onReportProblem() = lambdaError() + } + val params = LoginEntryPoint.Params( + accountProvider = "ac", + loginHint = "lh", + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(LoginFlowNode::class.java) + assertThat(result.plugins).contains(LoginFlowNode.Params(params.accountProvider, params.loginHint)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutView.kt b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutView.kt index 4d6b6df3d2..08a7047c1c 100644 --- a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutView.kt +++ b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutView.kt @@ -9,7 +9,7 @@ package io.element.android.features.logout.api.direct import androidx.compose.runtime.Composable -interface DirectLogoutView { +fun interface DirectLogoutView { @Composable fun Render(state: DirectLogoutState) } diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt new file mode 100644 index 0000000000..86300353b0 --- /dev/null +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.logout.api.LogoutEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultLogoutEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultLogoutEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + LogoutNode( + buildContext = buildContext, + plugins = plugins, + presenter = createLogoutPresenter(), + ) + } + val callback = object : LogoutEntryPoint.Callback { + override fun onChangeRecoveryKeyClick() = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(LogoutNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt index 3a309ab7b9..34406aa098 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt @@ -225,12 +225,12 @@ class LogoutPresenterTest { skipItems(2) return awaitItem() } - - private fun createLogoutPresenter( - matrixClient: MatrixClient = FakeMatrixClient(), - encryptionService: EncryptionService = FakeEncryptionService(), - ): LogoutPresenter = LogoutPresenter( - matrixClient = matrixClient, - encryptionService = encryptionService, - ) } + +internal fun createLogoutPresenter( + matrixClient: MatrixClient = FakeMatrixClient(), + encryptionService: EncryptionService = FakeEncryptionService(), +): LogoutPresenter = LogoutPresenter( + matrixClient = matrixClient, + encryptionService = encryptionService, +) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt new file mode 100644 index 0000000000..dd4f4e4d41 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt @@ -0,0 +1,121 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl + +import androidx.compose.runtime.Composable +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.ElementCallEntryPoint +import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint +import io.element.android.features.location.api.SendLocationEntryPoint +import io.element.android.features.location.api.ShowLocationEntryPoint +import io.element.android.features.location.test.FakeLocationService +import io.element.android.features.messages.api.MessagesEntryPoint +import io.element.android.features.messages.impl.pinned.banner.createPinnedEventsTimelineProvider +import io.element.android.features.messages.impl.timeline.createTimelineController +import io.element.android.features.poll.api.create.CreatePollEntryPoint +import io.element.android.libraries.dateformatter.test.FakeDateFormatter +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.permalink.PermalinkData +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.test.AN_EVENT_ID +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.room.FakeBaseRoom +import io.element.android.libraries.matrix.ui.messages.RoomMemberProfilesCache +import io.element.android.libraries.matrix.ui.messages.RoomNamesCache +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +import io.element.android.libraries.textcomposer.mentions.MentionSpanTheme +import io.element.android.libraries.textcomposer.mentions.MentionSpanUpdater +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultMessagesEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultMessagesEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + MessagesFlowNode( + buildContext = buildContext, + plugins = plugins, + matrixClient = FakeMatrixClient(), + sendLocationEntryPoint = object : SendLocationEntryPoint { + override fun builder(timelineMode: Timeline.Mode) = lambdaError() + }, + showLocationEntryPoint = object : ShowLocationEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext, inputs: ShowLocationEntryPoint.Inputs) = lambdaError() + }, + createPollEntryPoint = object : CreatePollEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + elementCallEntryPoint = object : ElementCallEntryPoint { + override fun startCall(callType: CallType) = lambdaError() + override suspend fun handleIncomingCall( + callType: CallType.RoomCall, + eventId: EventId, + senderId: UserId, + roomName: String?, + senderName: String?, + avatarUrl: String?, + timestamp: Long, + notificationChannelId: String, + textContent: String?, + ) = lambdaError() + }, + mediaViewerEntryPoint = object : MediaViewerEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + analyticsService = FakeAnalyticsService(), + locationService = FakeLocationService(), + room = FakeBaseRoom(), + roomMemberProfilesCache = RoomMemberProfilesCache(), + roomNamesCache = RoomNamesCache(), + mentionSpanUpdater = object : MentionSpanUpdater { + override fun updateMentionSpans(text: CharSequence) = text + + @Composable + override fun rememberMentionSpans(text: CharSequence) = text + }, + mentionSpanTheme = MentionSpanTheme(A_USER_ID), + pinnedEventsTimelineProvider = createPinnedEventsTimelineProvider(), + timelineController = createTimelineController(), + knockRequestsListEntryPoint = object : KnockRequestsListEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + dateFormatter = FakeDateFormatter(), + coroutineDispatchers = testCoroutineDispatchers(), + ) + } + val callback = object : MessagesEntryPoint.Callback { + override fun onRoomDetailsClick() = lambdaError() + override fun onUserDataClick(userId: UserId) = lambdaError() + override fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError() + override fun onForwardedToSingleRoom(roomId: RoomId) = lambdaError() + } + val initialTarget = MessagesEntryPoint.InitialTarget.Messages(focusedEventId = AN_EVENT_ID) + val params = MessagesEntryPoint.Params(initialTarget) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(MessagesFlowNode::class.java) + assertThat(result.plugins).contains(MessagesEntryPoint.Params(initialTarget)) + assertThat(result.plugins).contains(callback) + } +} 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 4840d5bed1..38182dec1d 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 @@ -178,10 +178,9 @@ class PinnedMessagesBannerPresenterTest { ), syncService: SyncService = FakeSyncService(), ): PinnedMessagesBannerPresenter { - val timelineProvider = PinnedEventsTimelineProvider( + val timelineProvider = createPinnedEventsTimelineProvider( room = room, syncService = syncService, - dispatchers = testCoroutineDispatchers(), ) timelineProvider.launchIn(backgroundScope) @@ -192,3 +191,12 @@ class PinnedMessagesBannerPresenterTest { ) } } + +internal fun TestScope.createPinnedEventsTimelineProvider( + room: JoinedRoom = FakeJoinedRoom(), + syncService: SyncService = FakeSyncService(), +) = PinnedEventsTimelineProvider( + room = room, + syncService = syncService, + dispatchers = testCoroutineDispatchers(), +) 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 a2005b7a39..71d295ba8b 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 @@ -217,3 +217,13 @@ class TimelineControllerTest { } } } + +internal fun createTimelineController( + room: FakeJoinedRoom = FakeJoinedRoom(liveTimeline = FakeTimeline()), + liveTimeline: Timeline = FakeTimeline(name = "live"), +): TimelineController { + return TimelineController( + room = room, + liveTimeline = liveTimeline + ) +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt index 134742f7d1..2d760d8314 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt @@ -47,7 +47,7 @@ class CreatePollPresenter( @Assisted private val timelineMode: Timeline.Mode, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create( timelineMode: Timeline.Mode, backNavigator: () -> Unit, diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/data/PollRepository.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/data/PollRepository.kt index 4fbb7f1499..983e3157a3 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/data/PollRepository.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/data/PollRepository.kt @@ -33,7 +33,7 @@ class PollRepository( @Assisted private val timelineMode: Timeline.Mode, ) { @AssistedFactory - interface Factory { + fun interface Factory { fun create( timelineMode: Timeline.Mode, ): PollRepository diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt new file mode 100644 index 0000000000..2150292c4c --- /dev/null +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.poll.impl.create + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.messages.test.FakeMessageComposerContext +import io.element.android.features.poll.api.create.CreatePollEntryPoint +import io.element.android.features.poll.api.create.CreatePollMode +import io.element.android.features.poll.impl.data.PollRepository +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.timeline.LiveTimelineProvider +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultCreatePollEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultCreatePollEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + CreatePollNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { timelineMode: Timeline.Mode, backNavigator: () -> Unit, mode: CreatePollMode -> + CreatePollPresenter( + repositoryFactory = { + val room = FakeJoinedRoom() + PollRepository(room, LiveTimelineProvider(room), timelineMode) + }, + analyticsService = FakeAnalyticsService(), + messageComposerContext = FakeMessageComposerContext(), + navigateUp = backNavigator, + mode = mode, + timelineMode = timelineMode, + ) + }, + analyticsService = FakeAnalyticsService(), + ) + } + val params = CreatePollEntryPoint.Params( + timelineMode = Timeline.Mode.Live, + mode = CreatePollMode.NewPoll, + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .build() + assertThat(result).isInstanceOf(CreatePollNode::class.java) + assertThat(result.plugins).contains(CreatePollNode.Inputs(timelineMode = params.timelineMode, mode = params.mode)) + } +} diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt new file mode 100644 index 0000000000..6d9e44a8a2 --- /dev/null +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.poll.impl.history + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.poll.api.create.CreatePollEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultPollHistoryEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultPollHistoryEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + PollHistoryFlowNode( + buildContext = buildContext, + plugins = plugins, + createPollEntryPoint = object : CreatePollEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + } + ) + } + val result = entryPoint.createNode(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(PollHistoryFlowNode::class.java) + } +} diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenterTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenterTest.kt index eeb4d0d223..cac5fae135 100644 --- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenterTest.kt +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenterTest.kt @@ -151,23 +151,23 @@ class PollHistoryPresenterTest { assert(paginateLambda).isCalledExactly(2) } } - - private fun TestScope.createPollHistoryPresenter( - room: FakeJoinedRoom = FakeJoinedRoom(), - endPollAction: EndPollAction = FakeEndPollAction(), - sendPollResponseAction: SendPollResponseAction = FakeSendPollResponseAction(), - pollHistoryItemFactory: PollHistoryItemsFactory = PollHistoryItemsFactory( - pollContentStateFactory = DefaultPollContentStateFactory(FakeMatrixClient()), - dateFormatter = FakeDateFormatter(), - dispatchers = testCoroutineDispatchers(), - ), - ): PollHistoryPresenter { - return PollHistoryPresenter( - sessionCoroutineScope = this, - sendPollResponseAction = sendPollResponseAction, - endPollAction = endPollAction, - pollHistoryItemFactory = pollHistoryItemFactory, - room = room, - ) - } +} + +internal fun TestScope.createPollHistoryPresenter( + room: FakeJoinedRoom = FakeJoinedRoom(), + endPollAction: EndPollAction = FakeEndPollAction(), + sendPollResponseAction: SendPollResponseAction = FakeSendPollResponseAction(), + pollHistoryItemFactory: PollHistoryItemsFactory = PollHistoryItemsFactory( + pollContentStateFactory = DefaultPollContentStateFactory(FakeMatrixClient()), + dateFormatter = FakeDateFormatter(), + dispatchers = testCoroutineDispatchers(), + ), +): PollHistoryPresenter { + return PollHistoryPresenter( + sessionCoroutineScope = this, + sendPollResponseAction = sendPollResponseAction, + endPollAction = endPollAction, + pollHistoryItemFactory = pollHistoryItemFactory, + room = room, + ) } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt new file mode 100644 index 0000000000..971ca6ab51 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.preferences.impl + +import android.content.Context +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.deactivation.api.AccountDeactivationEntryPoint +import io.element.android.features.licenses.api.OpenSourceLicensesEntryPoint +import io.element.android.features.lockscreen.api.LockScreenEntryPoint +import io.element.android.features.logout.api.LogoutEntryPoint +import io.element.android.features.preferences.api.PreferencesEntryPoint +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.troubleshoot.api.NotificationTroubleShootEntryPoint +import io.element.android.libraries.troubleshoot.api.PushHistoryEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultPreferencesEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultPreferencesEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + PreferencesFlowNode( + buildContext = buildContext, + plugins = plugins, + lockScreenEntryPoint = object : LockScreenEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext, navTarget: LockScreenEntryPoint.Target) = lambdaError() + override fun pinUnlockIntent(context: Context) = lambdaError() + }, + notificationTroubleShootEntryPoint = object : NotificationTroubleShootEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + pushHistoryEntryPoint = object : PushHistoryEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + logoutEntryPoint = object : LogoutEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + openSourceLicensesEntryPoint = object : OpenSourceLicensesEntryPoint { + override fun getNode(node: Node, buildContext: BuildContext) = lambdaError() + }, + accountDeactivationEntryPoint = object : AccountDeactivationEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + ) + } + val callback = object : PreferencesEntryPoint.Callback { + override fun onOpenBugReport() = lambdaError() + override fun onSecureBackupClick() = lambdaError() + override fun onOpenRoomNotificationSettings(roomId: RoomId) = lambdaError() + override fun navigateTo(sessionId: SessionId, roomId: RoomId, eventId: EventId) = lambdaError() + } + val params = PreferencesEntryPoint.Params( + initialElement = PreferencesEntryPoint.InitialTarget.NotificationSettings, + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(PreferencesFlowNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt index 027e2fb38c..362b3798d6 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt @@ -225,15 +225,15 @@ class BugReportPresenterTest { assertThat(awaitItem().sending).isEqualTo(AsyncAction.Uninitialized) } } - - private fun TestScope.createPresenter( - bugReporter: BugReporter = FakeBugReporter(), - crashDataStore: CrashDataStore = FakeCrashDataStore(), - screenshotHolder: ScreenshotHolder = FakeScreenshotHolder(), - ) = BugReportPresenter( - bugReporter = bugReporter, - crashDataStore = crashDataStore, - screenshotHolder = screenshotHolder, - appCoroutineScope = this, - ) } + +internal fun TestScope.createPresenter( + bugReporter: BugReporter = FakeBugReporter(), + crashDataStore: CrashDataStore = FakeCrashDataStore(), + screenshotHolder: ScreenshotHolder = FakeScreenshotHolder(), +) = BugReportPresenter( + bugReporter = bugReporter, + crashDataStore = crashDataStore, + screenshotHolder = screenshotHolder, + appCoroutineScope = this, +) diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt new file mode 100644 index 0000000000..5ea1bb23db --- /dev/null +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.rageshake.impl.bugreport + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultBugReportEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultBugReportEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + BugReportNode( + buildContext = buildContext, + plugins = plugins, + presenter = createPresenter(), + bugReporter = FakeBugReporter(), + ) + } + val callback = object : BugReportEntryPoint.Callback { + override fun onBugReportSent() = lambdaError() + override fun onViewLogs(basePath: String) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(BugReportNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/reportroom/api/src/main/kotlin/io/element/android/features/reportroom/api/ReportRoomEntryPoint.kt b/features/reportroom/api/src/main/kotlin/io/element/android/features/reportroom/api/ReportRoomEntryPoint.kt index 7f531fb9e3..1eff7f8206 100644 --- a/features/reportroom/api/src/main/kotlin/io/element/android/features/reportroom/api/ReportRoomEntryPoint.kt +++ b/features/reportroom/api/src/main/kotlin/io/element/android/features/reportroom/api/ReportRoomEntryPoint.kt @@ -12,6 +12,6 @@ import com.bumble.appyx.core.node.Node import io.element.android.libraries.architecture.FeatureEntryPoint import io.element.android.libraries.matrix.api.core.RoomId -interface ReportRoomEntryPoint : FeatureEntryPoint { +fun interface ReportRoomEntryPoint : FeatureEntryPoint { fun createNode(parentNode: Node, buildContext: BuildContext, roomId: RoomId): Node } diff --git a/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenter.kt b/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenter.kt index fccea0e576..f47ab19004 100644 --- a/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenter.kt +++ b/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenter.kt @@ -31,7 +31,7 @@ class ReportRoomPresenter( private val reportRoom: ReportRoom, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(roomId: RoomId): ReportRoomPresenter } diff --git a/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt new file mode 100644 index 0000000000..c8d5998149 --- /dev/null +++ b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.reportroom.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultReportRoomEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultReportRoomEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ReportRoomNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { roomId -> + assertThat(roomId).isEqualTo(A_ROOM_ID) + createReportRoomPresenter() + } + ) + } + val result = entryPoint.createNode(parentNode, BuildContext.root(null), A_ROOM_ID) + assertThat(result).isInstanceOf(ReportRoomNode::class.java) + assertThat(result.plugins).contains(ReportRoomNode.Inputs(A_ROOM_ID)) + } +} diff --git a/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenterTest.kt b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenterTest.kt index d85f2b86e8..eb2e94366d 100644 --- a/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenterTest.kt +++ b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenterTest.kt @@ -141,11 +141,11 @@ class ReportRoomPresenterTest { ) } } - - fun createReportRoomPresenter( - roomId: RoomId = A_ROOM_ID, - reportRoom: ReportRoom = FakeReportRoom() - ): ReportRoomPresenter { - return ReportRoomPresenter(roomId, reportRoom) - } +} + +internal fun createReportRoomPresenter( + roomId: RoomId = A_ROOM_ID, + reportRoom: ReportRoom = FakeReportRoom() +): ReportRoomPresenter { + return ReportRoomPresenter(roomId, reportRoom) } diff --git a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt index 95ed62a819..9b65d3e14a 100644 --- a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt +++ b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt @@ -30,7 +30,7 @@ class RoomAliasResolverPresenter( @Assisted private val roomAlias: RoomAlias, private val matrixClient: MatrixClient, ) : Presenter { - interface Factory { + fun interface Factory { fun create( roomAlias: RoomAlias, ): RoomAliasResolverPresenter diff --git a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt new file mode 100644 index 0000000000..efd25c60df --- /dev/null +++ b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roomaliasresolver.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.roomaliasesolver.api.RoomAliasResolverEntryPoint +import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultRoomAliasResolverEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultRoomAliasResolverEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + RoomAliasResolverNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { alias -> + assertThat(alias).isEqualTo(A_ROOM_ALIAS) + createPresenter( + alias, + ) + } + + ) + } + val callback = object : RoomAliasResolverEntryPoint.Callback { + override fun onAliasResolved(data: ResolvedRoomAlias) = lambdaError() + } + val params = RoomAliasResolverEntryPoint.Params( + roomAlias = A_ROOM_ALIAS + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(RoomAliasResolverNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperPresenterTest.kt b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperPresenterTest.kt index 3071d8943a..f90b07c91b 100644 --- a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperPresenterTest.kt +++ b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperPresenterTest.kt @@ -79,16 +79,16 @@ class RoomAliasHelperPresenterTest { assertThat(retryState.resolveState.errorOrNull()).isEqualTo(AN_EXCEPTION) } } - - private fun createPresenter( - roomAlias: RoomAlias = A_ROOM_ALIAS, - matrixClient: MatrixClient = FakeMatrixClient(), - ) = RoomAliasResolverPresenter( - roomAlias = roomAlias, - matrixClient = matrixClient, - ) } +internal fun createPresenter( + roomAlias: RoomAlias = A_ROOM_ALIAS, + matrixClient: MatrixClient = FakeMatrixClient(), +) = RoomAliasResolverPresenter( + roomAlias = roomAlias, + matrixClient = matrixClient, +) + internal fun aResolvedRoomAlias( roomId: RoomId = A_ROOM_ID, servers: List = A_SERVER_LIST, diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt new file mode 100644 index 0000000000..e863b7b562 --- /dev/null +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt @@ -0,0 +1,105 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roomdetails.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.ElementCallEntryPoint +import io.element.android.features.changeroommemberroes.api.ChangeRoomMemberRolesEntryPoint +import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint +import io.element.android.features.messages.api.MessagesEntryPoint +import io.element.android.features.poll.api.history.PollHistoryEntryPoint +import io.element.android.features.reportroom.api.ReportRoomEntryPoint +import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint +import io.element.android.features.verifysession.api.OutgoingVerificationEntryPoint +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.permalink.PermalinkData +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultRoomDetailsEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultRoomDetailsEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + RoomDetailsFlowNode( + buildContext = buildContext, + plugins = plugins, + pollHistoryEntryPoint = object : PollHistoryEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + elementCallEntryPoint = object : ElementCallEntryPoint { + override fun startCall(callType: CallType) = lambdaError() + override suspend fun handleIncomingCall( + callType: CallType.RoomCall, + eventId: EventId, + senderId: UserId, + roomName: String?, + senderName: String?, + avatarUrl: String?, + timestamp: Long, + notificationChannelId: String, + textContent: String? + ) = lambdaError() + }, + room = FakeJoinedRoom(), + analyticsService = FakeAnalyticsService(), + messagesEntryPoint = object : MessagesEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + knockRequestsListEntryPoint = object : KnockRequestsListEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + mediaViewerEntryPoint = object : MediaViewerEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + mediaGalleryEntryPoint = object : MediaGalleryEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + outgoingVerificationEntryPoint = object : OutgoingVerificationEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + reportRoomEntryPoint = object : ReportRoomEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext, roomId: RoomId) = lambdaError() + }, + changeRoomMemberRolesEntryPoint = object : ChangeRoomMemberRolesEntryPoint { + override fun builder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + ) + } + val callback = object : RoomDetailsEntryPoint.Callback { + override fun onOpenGlobalNotificationSettings() = lambdaError() + override fun onOpenRoom(roomId: RoomId, serverNames: List) = lambdaError() + override fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError() + override fun onForwardedToSingleRoom(roomId: RoomId) = lambdaError() + } + val params = RoomDetailsEntryPoint.Params( + initialElement = RoomDetailsEntryPoint.InitialTarget.RoomDetails, + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(RoomDetailsFlowNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt new file mode 100644 index 0000000000..fc3ffa2ec3 --- /dev/null +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roomdirectory.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.roomdirectory.api.RoomDescription +import io.element.android.features.roomdirectory.api.RoomDirectoryEntryPoint +import io.element.android.features.roomdirectory.impl.root.RoomDirectoryNode +import io.element.android.features.roomdirectory.impl.root.createRoomDirectoryPresenter +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultRoomDirectoryEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultRoomDirectoryEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + RoomDirectoryNode( + buildContext = buildContext, + plugins = plugins, + presenter = createRoomDirectoryPresenter(), + ) + } + val callback = object : RoomDirectoryEntryPoint.Callback { + override fun onResultClick(roomDescription: RoomDescription) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(RoomDirectoryNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt index d6ebb6cd95..4af983b307 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt @@ -122,15 +122,15 @@ class RoomDirectoryPresenterTest { .isCalledOnce() .withNoParameter() } - - private fun TestScope.createRoomDirectoryPresenter( - roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService( - createRoomDirectoryListFactory = { FakeRoomDirectoryList() } - ), - ): RoomDirectoryPresenter { - return RoomDirectoryPresenter( - dispatchers = testCoroutineDispatchers(), - roomDirectoryService = roomDirectoryService, - ) - } +} + +internal fun TestScope.createRoomDirectoryPresenter( + roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService( + createRoomDirectoryListFactory = { FakeRoomDirectoryList() } + ), +): RoomDirectoryPresenter { + return RoomDirectoryPresenter( + dispatchers = testCoroutineDispatchers(), + roomDirectoryService = roomDirectoryService, + ) } diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt new file mode 100644 index 0000000000..13a00ff046 --- /dev/null +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.securebackup.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.securebackup.api.SecureBackupEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultSecureBackupEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultSecureBackupEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + SecureBackupFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val callback = object : SecureBackupEntryPoint.Callback { + override fun onDone() = lambdaError() + } + val params = SecureBackupEntryPoint.Params(SecureBackupEntryPoint.InitialTarget.ResetIdentity) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(SecureBackupFlowNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} 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 aaadf6f8d0..056d8b912e 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 @@ -43,7 +43,7 @@ class SharePresenter( private val mediaOptimizationConfigProvider: MediaOptimizationConfigProvider, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(intent: Intent): SharePresenter } diff --git a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt new file mode 100644 index 0000000000..2762af89c7 --- /dev/null +++ b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.share.impl + +import android.content.Intent +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.share.api.ShareEntryPoint +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.roomselect.api.RoomSelectEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultShareEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultShareEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ShareNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { createSharePresenter() }, + roomSelectEntryPoint = object : RoomSelectEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): RoomSelectEntryPoint.NodeBuilder { + lambdaError() + } + }, + ) + } + val callback = object : ShareEntryPoint.Callback { + override fun onDone(roomIds: List) = lambdaError() + } + val params = ShareEntryPoint.Params( + intent = Intent(), + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(ShareNode::class.java) + assertThat(result.plugins).contains(ShareNode.Inputs(params.intent)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt index 7ddb7d0ae4..b1b39b2e80 100644 --- a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt +++ b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt @@ -158,23 +158,23 @@ class SharePresenterTest { sendFileResult.assertions().isCalledOnce() } } - - private fun TestScope.createSharePresenter( - intent: Intent = Intent(), - shareIntentHandler: ShareIntentHandler = FakeShareIntentHandler(), - matrixClient: MatrixClient = FakeMatrixClient(), - mediaPreProcessor: MediaPreProcessor = FakeMediaPreProcessor(), - activeRoomsHolder: ActiveRoomsHolder = ActiveRoomsHolder(), - mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), - ): SharePresenter { - return SharePresenter( - intent = intent, - sessionCoroutineScope = this, - shareIntentHandler = shareIntentHandler, - matrixClient = matrixClient, - mediaPreProcessor = mediaPreProcessor, - activeRoomsHolder = activeRoomsHolder, - mediaOptimizationConfigProvider = mediaOptimizationConfigProvider, - ) - } +} + +internal fun TestScope.createSharePresenter( + intent: Intent = Intent(), + shareIntentHandler: ShareIntentHandler = FakeShareIntentHandler(), + matrixClient: MatrixClient = FakeMatrixClient(), + mediaPreProcessor: MediaPreProcessor = FakeMediaPreProcessor(), + activeRoomsHolder: ActiveRoomsHolder = ActiveRoomsHolder(), + mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), +): SharePresenter { + return SharePresenter( + intent = intent, + sessionCoroutineScope = this, + shareIntentHandler = shareIntentHandler, + matrixClient = matrixClient, + mediaPreProcessor = mediaPreProcessor, + activeRoomsHolder = activeRoomsHolder, + mediaOptimizationConfigProvider = mediaOptimizationConfigProvider, + ) } diff --git a/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutPresenter.kt b/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutPresenter.kt index 6516a2a1c6..9810892ff3 100644 --- a/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutPresenter.kt +++ b/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutPresenter.kt @@ -29,7 +29,7 @@ class SignedOutPresenter( private val buildMeta: BuildMeta, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(sessionId: String): SignedOutPresenter } diff --git a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt new file mode 100644 index 0000000000..0edcbf2054 --- /dev/null +++ b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.signedout.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.signedout.api.SignedOutEntryPoint +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultSignedOutEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultSignedOutEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + SignedOutNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { sessionId -> + assertThat(sessionId).isEqualTo(A_SESSION_ID.value) + createSignedOutPresenter() + } + ) + } + val params = SignedOutEntryPoint.Params(A_SESSION_ID) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .build() + assertThat(result).isInstanceOf(SignedOutNode::class.java) + assertThat(result.plugins).contains(SignedOutNode.Inputs(params.sessionId)) + } +} diff --git a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt index 8674020f1e..d3a52c8b37 100644 --- a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt +++ b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt @@ -22,12 +22,12 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +private val appName = "AppName" + class SignedOutPresenterTest { @get:Rule val warmUpRule = WarmUpRule() - private val appName = "AppName" - @Test fun `present - initial state`() = runTest { val aSessionData = aSessionData() @@ -64,15 +64,15 @@ class SignedOutPresenterTest { assertThat(sessionStore.getAllSessions()).isEmpty() } } - - private fun createSignedOutPresenter( - sessionId: SessionId = A_SESSION_ID, - sessionStore: SessionStore = InMemorySessionStore(), - ): SignedOutPresenter { - return SignedOutPresenter( - sessionId = sessionId.value, - sessionStore = sessionStore, - buildMeta = aBuildMeta(applicationName = appName), - ) - } +} + +internal fun createSignedOutPresenter( + sessionId: SessionId = A_SESSION_ID, + sessionStore: SessionStore = InMemorySessionStore(), +): SignedOutPresenter { + return SignedOutPresenter( + sessionId = sessionId.value, + sessionStore = sessionStore, + buildMeta = aBuildMeta(applicationName = appName), + ) } diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt index a0afb36630..f57ee5cafb 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt @@ -25,7 +25,7 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class DefaultSpaceEntryPointTest { @Test - fun `test DefaultSpaceEntryPoint`() { + fun `test node builder`() { val entryPoint = DefaultSpaceEntryPoint() val nodeInputs = SpaceEntryPoint.Inputs(A_ROOM_ID) val parentNode = TestParentNode.create { buildContext, plugins -> diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt new file mode 100644 index 0000000000..351ccb651a --- /dev/null +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.createroom.api.CreateRoomEntryPoint +import io.element.android.features.startchat.api.StartChatEntryPoint +import io.element.android.features.startchat.impl.root.StartChatNode +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultStartChatEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultStartChatEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + StartChatFlowNode( + buildContext = buildContext, + plugins = plugins, + createRoomEntryPoint = object : CreateRoomEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + ) + } + val callback = object : StartChatEntryPoint.Callback { + override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List) = lambdaError() + override fun onOpenRoomDirectory() = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(StartChatFlowNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt index 59a8838c6b..7340981053 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt @@ -177,23 +177,23 @@ class StartChatPresenterTest { } } } - - private fun createStartChatPresenter( - startDMAction: StartDMAction = FakeStartDMAction(), - isRoomDirectorySearchEnabled: Boolean = false, - ): StartChatPresenter { - val featureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.RoomDirectorySearch.key to isRoomDirectorySearchEnabled, - ), - ) - return StartChatPresenter( - presenterFactory = FakeUserListPresenterFactory(FakeUserListPresenter()), - userRepository = FakeUserRepository(), - userListDataStore = UserListDataStore(), - startDMAction = startDMAction, - featureFlagService = featureFlagService, - buildMeta = aBuildMeta(), - ) - } +} + +internal fun createStartChatPresenter( + startDMAction: StartDMAction = FakeStartDMAction(), + isRoomDirectorySearchEnabled: Boolean = false, +): StartChatPresenter { + val featureFlagService = FakeFeatureFlagService( + initialState = mapOf( + FeatureFlags.RoomDirectorySearch.key to isRoomDirectorySearchEnabled, + ), + ) + return StartChatPresenter( + presenterFactory = FakeUserListPresenterFactory(FakeUserListPresenter()), + userRepository = FakeUserRepository(), + userListDataStore = UserListDataStore(), + startDMAction = startDMAction, + featureFlagService = featureFlagService, + buildMeta = aBuildMeta(), + ) } diff --git a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt new file mode 100644 index 0000000000..266d709ccf --- /dev/null +++ b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.userprofile.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.ElementCallEntryPoint +import io.element.android.features.userprofile.api.UserProfileEntryPoint +import io.element.android.features.verifysession.api.OutgoingVerificationEntryPoint +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultUserProfileEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultUserProfileEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + UserProfileFlowNode( + buildContext = buildContext, + plugins = plugins, + sessionIdHolder = CurrentSessionIdHolder(FakeMatrixClient()), + elementCallEntryPoint = object : ElementCallEntryPoint { + override fun startCall(callType: CallType) = lambdaError() + override suspend fun handleIncomingCall( + callType: CallType.RoomCall, + eventId: EventId, + senderId: UserId, + roomName: String?, + senderName: String?, + avatarUrl: String?, + timestamp: Long, + notificationChannelId: String, + textContent: String? + ) = lambdaError() + }, + mediaViewerEntryPoint = object : MediaViewerEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + outgoingVerificationEntryPoint = object : OutgoingVerificationEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + ) + } + val callback = object : UserProfileEntryPoint.Callback { + override fun onOpenRoom(roomId: RoomId) { + lambdaError() + } + } + val params = UserProfileEntryPoint.Params( + userId = A_USER_ID, + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(UserProfileFlowNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenter.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenter.kt index aab6ff0329..8be176f117 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenter.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenter.kt @@ -48,7 +48,7 @@ class IncomingVerificationPresenter( private val dateFormatter: DateFormatter, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create( verificationRequest: VerificationRequest.Incoming, navigator: IncomingVerificationNavigator, diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenter.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenter.kt index 5b6004845d..84ebec96de 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenter.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenter.kt @@ -42,7 +42,7 @@ class OutgoingVerificationPresenter( private val encryptionService: EncryptionService, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create( verificationRequest: VerificationRequest.Outgoing, showDeviceVerifiedScreen: Boolean, diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt new file mode 100644 index 0000000000..b3ac839b54 --- /dev/null +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.verifysession.impl.incoming + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.verifysession.api.IncomingVerificationEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultIncomingVerificationEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultIncomingVerificationEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + IncomingVerificationNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { _, _ -> createPresenter() } + ) + } + val callback = object : IncomingVerificationEntryPoint.Callback { + override fun onDone() = lambdaError() + } + val params = IncomingVerificationEntryPoint.Params( + verificationRequest = anIncomingSessionVerificationRequest() + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(IncomingVerificationNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt index 8fdf62df4f..06c4956ea9 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt @@ -289,31 +289,31 @@ class IncomingVerificationPresenterTest { navigatorLambda.assertions().isCalledOnce() } } - - private val anIncomingSessionVerificationRequest = VerificationRequest.Incoming.OtherSession( - details = SessionVerificationRequestDetails( - senderProfile = SessionVerificationRequestDetails.SenderProfile( - userId = A_USER_ID, - displayName = "a device name", - avatarUrl = null, - ), - flowId = FlowId("flowId"), - deviceId = A_DEVICE_ID, - firstSeenTimestamp = A_TIMESTAMP, - ) - ) - - private fun TestScope.createPresenter( - verificationRequest: VerificationRequest.Incoming = anIncomingSessionVerificationRequest, - navigator: IncomingVerificationNavigator = IncomingVerificationNavigator { lambdaError() }, - service: SessionVerificationService = FakeSessionVerificationService(), - dateFormatter: DateFormatter = FakeDateFormatter(), - ) = IncomingVerificationPresenter( - verificationRequest = verificationRequest, - navigator = navigator, - sessionVerificationService = service, - stateMachine = IncomingVerificationStateMachine(service), - dateFormatter = dateFormatter, - sessionCoroutineScope = backgroundScope, - ) } + +private val anIncomingSessionVerificationRequest = VerificationRequest.Incoming.OtherSession( + details = SessionVerificationRequestDetails( + senderProfile = SessionVerificationRequestDetails.SenderProfile( + userId = A_USER_ID, + displayName = "a device name", + avatarUrl = null, + ), + flowId = FlowId("flowId"), + deviceId = A_DEVICE_ID, + firstSeenTimestamp = A_TIMESTAMP, + ) +) + +internal fun TestScope.createPresenter( + verificationRequest: VerificationRequest.Incoming = anIncomingSessionVerificationRequest, + navigator: IncomingVerificationNavigator = IncomingVerificationNavigator { lambdaError() }, + service: SessionVerificationService = FakeSessionVerificationService(), + dateFormatter: DateFormatter = FakeDateFormatter(), +) = IncomingVerificationPresenter( + verificationRequest = verificationRequest, + navigator = navigator, + sessionVerificationService = service, + stateMachine = IncomingVerificationStateMachine(service), + dateFormatter = dateFormatter, + sessionCoroutineScope = backgroundScope, +) diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt new file mode 100644 index 0000000000..f4b53a133c --- /dev/null +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.verifysession.impl.outgoing + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.verifysession.api.OutgoingVerificationEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultOutgoingVerificationEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultOutgoingVerificationEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + OutgoingVerificationNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { _, _ -> + createOutgoingVerificationPresenter() + } + ) + } + val callback = object : OutgoingVerificationEntryPoint.Callback { + override fun onLearnMoreAboutEncryption() = lambdaError() + override fun onBack() = lambdaError() + override fun onDone() = lambdaError() + } + val params = OutgoingVerificationEntryPoint.Params( + showDeviceVerifiedScreen = true, + verificationRequest = anOutgoingSessionVerificationRequest(), + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(OutgoingVerificationNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt index 06940f37a5..2eac19d018 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt @@ -321,18 +321,18 @@ class OutgoingVerificationPresenterTest { emitVerifiedStatus(SessionVerifiedStatus.NotVerified) } } - - private fun createOutgoingVerificationPresenter( - service: SessionVerificationService, - verificationRequest: VerificationRequest.Outgoing = anOutgoingSessionVerificationRequest(), - encryptionService: EncryptionService = FakeEncryptionService(), - showDeviceVerifiedScreen: Boolean = false, - ): OutgoingVerificationPresenter { - return OutgoingVerificationPresenter( - showDeviceVerifiedScreen = showDeviceVerifiedScreen, - verificationRequest = verificationRequest, - sessionVerificationService = service, - encryptionService = encryptionService, - ) - } +} + +internal fun createOutgoingVerificationPresenter( + service: SessionVerificationService = FakeSessionVerificationService(), + verificationRequest: VerificationRequest.Outgoing = anOutgoingSessionVerificationRequest(), + encryptionService: EncryptionService = FakeEncryptionService(), + showDeviceVerifiedScreen: Boolean = false, +): OutgoingVerificationPresenter { + return OutgoingVerificationPresenter( + showDeviceVerifiedScreen = showDeviceVerifiedScreen, + verificationRequest = verificationRequest, + sessionVerificationService = service, + encryptionService = encryptionService, + ) } diff --git a/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt b/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt new file mode 100644 index 0000000000..dc2431c986 --- /dev/null +++ b/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.viewfolder.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.viewfolder.api.ViewFolderEntryPoint +import io.element.android.features.viewfolder.impl.root.ViewFolderRootNode +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultViewFolderEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultViewFolderEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ViewFolderRootNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val callback = object : ViewFolderEntryPoint.Callback { + override fun onDone() = lambdaError() + } + val params = ViewFolderEntryPoint.Params( + rootPath = "path", + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(ViewFolderRootNode::class.java) + assertThat(result.plugins).contains(ViewFolderRootNode.Inputs(params.rootPath)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/FeatureEntryPoint.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/FeatureEntryPoint.kt index 2a64bb7c98..d5a932b705 100644 --- a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/FeatureEntryPoint.kt +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/FeatureEntryPoint.kt @@ -18,6 +18,6 @@ interface FeatureEntryPoint /** * Can be used when the feature only exposes a simple node without the need of plugins. */ -interface SimpleFeatureEntryPoint : FeatureEntryPoint { +fun interface SimpleFeatureEntryPoint : FeatureEntryPoint { fun createNode(parentNode: Node, buildContext: BuildContext): Node } diff --git a/libraries/deeplink/api/src/main/kotlin/io/element/android/libraries/deeplink/api/usecase/InviteFriendsUseCase.kt b/libraries/deeplink/api/src/main/kotlin/io/element/android/libraries/deeplink/api/usecase/InviteFriendsUseCase.kt index 5c5bcf5043..7c8910e156 100644 --- a/libraries/deeplink/api/src/main/kotlin/io/element/android/libraries/deeplink/api/usecase/InviteFriendsUseCase.kt +++ b/libraries/deeplink/api/src/main/kotlin/io/element/android/libraries/deeplink/api/usecase/InviteFriendsUseCase.kt @@ -9,6 +9,6 @@ package io.element.android.libraries.deeplink.api.usecase import android.app.Activity -interface InviteFriendsUseCase { +fun interface InviteFriendsUseCase { fun execute(activity: Activity) } diff --git a/libraries/mediaviewer/impl/build.gradle.kts b/libraries/mediaviewer/impl/build.gradle.kts index acddcfcf76..4af1c54f46 100644 --- a/libraries/mediaviewer/impl/build.gradle.kts +++ b/libraries/mediaviewer/impl/build.gradle.kts @@ -54,6 +54,7 @@ dependencies { implementation(projects.libraries.matrix.api) testCommonDependencies(libs, true) + testImplementation(projects.libraries.audio.test) testImplementation(projects.libraries.dateformatter.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FocusedTimelineMediaGalleryDataSourceFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FocusedTimelineMediaGalleryDataSourceFactory.kt index 1d5df9025b..5d998d25fd 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FocusedTimelineMediaGalleryDataSourceFactory.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FocusedTimelineMediaGalleryDataSourceFactory.kt @@ -14,7 +14,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.mediaviewer.impl.model.MediaItem -interface FocusedTimelineMediaGalleryDataSourceFactory { +fun interface FocusedTimelineMediaGalleryDataSourceFactory { fun createFor( eventId: EventId, mediaItem: MediaItem.Event, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt index b2534f3f71..93ef09cf4f 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt @@ -58,7 +58,7 @@ class MediaViewerPresenter( private val localMediaActions: LocalMediaActions, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create( inputs: MediaViewerEntryPoint.Params, navigator: MediaViewerNavigator, diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt new file mode 100644 index 0000000000..27dc68e75e --- /dev/null +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.mediaviewer.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +import io.element.android.libraries.mediaviewer.impl.gallery.root.MediaGalleryRootNode +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultMediaGalleryEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultMediaGalleryEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + MediaGalleryRootNode( + buildContext = buildContext, + plugins = plugins, + mediaViewerEntryPoint = object : MediaViewerEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + } + ) + } + val callback = object : MediaGalleryEntryPoint.Callback { + override fun onBackClick() = lambdaError() + override fun onViewInTimeline(eventId: EventId) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(MediaGalleryRootNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt new file mode 100644 index 0000000000..90ff2f4e70 --- /dev/null +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt @@ -0,0 +1,145 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.mediaviewer.impl + +import android.net.Uri +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.core.mimetype.MimeTypes +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.media.MediaSource +import io.element.android.libraries.matrix.test.media.FakeMatrixMediaLoader +import io.element.android.libraries.mediaplayer.test.FakeAudioFocus +import io.element.android.libraries.mediaviewer.api.MediaInfo +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +import io.element.android.libraries.mediaviewer.impl.datasource.createTimelineMediaGalleryDataSource +import io.element.android.libraries.mediaviewer.impl.viewer.MediaViewerNode +import io.element.android.libraries.mediaviewer.impl.viewer.PagerKeysHandler +import io.element.android.libraries.mediaviewer.impl.viewer.createMediaViewerEntryPointParams +import io.element.android.libraries.mediaviewer.impl.viewer.createMediaViewerPresenter +import io.element.android.libraries.mediaviewer.test.FakeLocalMediaFactory +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import io.element.android.tests.testutils.testCoroutineDispatchers +import io.mockk.mockk +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultMediaViewerEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultMediaViewerEntryPoint() + val mockMediaUri: Uri = mockk("localMediaUri") + val localMediaFactory = FakeLocalMediaFactory(mockMediaUri) + val parentNode = TestParentNode.create { buildContext, plugins -> + MediaViewerNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { _, _, _ -> + createMediaViewerPresenter( + localMediaFactory = localMediaFactory, + ) + }, + timelineMediaGalleryDataSource = createTimelineMediaGalleryDataSource(), + focusedTimelineMediaGalleryDataSourceFactory = { _, _, _ -> + lambdaError() + }, + mediaLoader = FakeMatrixMediaLoader(), + localMediaFactory = FakeLocalMediaFactory(mockMediaUri), + coroutineDispatchers = testCoroutineDispatchers(), + systemClock = FakeSystemClock(), + pagerKeysHandler = PagerKeysHandler(), + textFileViewer = { _, _ -> lambdaError() }, + audioFocus = FakeAudioFocus(), + ) + } + val callback = object : MediaViewerEntryPoint.Callback { + override fun onDone() = lambdaError() + override fun onViewInTimeline(eventId: EventId) = lambdaError() + } + val params = createMediaViewerEntryPointParams() + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(MediaViewerNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } + + @Test + fun `test node builder avatar`() = runTest { + val entryPoint = DefaultMediaViewerEntryPoint() + val mockMediaUri: Uri = mockk("localMediaUri") + val localMediaFactory = FakeLocalMediaFactory(mockMediaUri) + val parentNode = TestParentNode.create { buildContext, plugins -> + MediaViewerNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { _, _, _ -> + createMediaViewerPresenter( + localMediaFactory = localMediaFactory, + ) + }, + timelineMediaGalleryDataSource = createTimelineMediaGalleryDataSource(), + focusedTimelineMediaGalleryDataSourceFactory = { _, _, _ -> + lambdaError() + }, + mediaLoader = FakeMatrixMediaLoader(), + localMediaFactory = FakeLocalMediaFactory(mockMediaUri), + coroutineDispatchers = testCoroutineDispatchers(), + systemClock = FakeSystemClock(), + pagerKeysHandler = PagerKeysHandler(), + textFileViewer = { _, _ -> lambdaError() }, + audioFocus = FakeAudioFocus(), + ) + } + val callback = object : MediaViewerEntryPoint.Callback { + override fun onDone() = lambdaError() + override fun onViewInTimeline(eventId: EventId) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .avatar( + filename = "fn", + avatarUrl = "avatarUrl", + ) + .callback(callback) + .build() + assertThat(result).isInstanceOf(MediaViewerNode::class.java) + assertThat(result.plugins).contains( + MediaViewerEntryPoint.Params( + mode = MediaViewerEntryPoint.MediaViewerMode.SingleMedia, + eventId = null, + mediaInfo = MediaInfo( + filename = "fn", + fileSize = null, + caption = null, + mimeType = MimeTypes.Images, + formattedFileSize = "", + fileExtension = "", + senderId = UserId("@dummy:server.org"), + senderName = null, + senderAvatar = null, + dateSent = null, + dateSentFull = null, + waveform = null, + duration = null, + ), + mediaSource = MediaSource(url = "avatarUrl"), + thumbnailSource = null, + canShowInfo = false, + ) + ) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt index 7e9f1870f5..771c82e4a2 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt @@ -255,19 +255,19 @@ class TimelineMediaGalleryDataSourceTest { ) } } +} - private fun TestScope.createTimelineMediaGalleryDataSource( - room: JoinedRoom = FakeJoinedRoom( - liveTimeline = FakeTimeline(), - ), - ): TimelineMediaGalleryDataSource { - return TimelineMediaGalleryDataSource( - room = room, - mediaTimeline = LiveMediaTimeline(room), - timelineMediaItemsFactory = createTimelineMediaItemsFactory(), - mediaItemsPostProcessor = MediaItemsPostProcessor(), - ) - } +internal fun TestScope.createTimelineMediaGalleryDataSource( + room: JoinedRoom = FakeJoinedRoom( + liveTimeline = FakeTimeline(), + ), +): TimelineMediaGalleryDataSource { + return TimelineMediaGalleryDataSource( + room = room, + mediaTimeline = LiveMediaTimeline(room), + timelineMediaItemsFactory = createTimelineMediaItemsFactory(), + mediaItemsPostProcessor = MediaItemsPostProcessor(), + ) } fun TestScope.createTimelineMediaItemsFactory() = TimelineMediaItemsFactory( diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt index e01eb53efb..b9964d8d3d 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt @@ -29,6 +29,7 @@ import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.api.anApkMediaInfo +import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory import io.element.android.libraries.mediaviewer.impl.R import io.element.android.libraries.mediaviewer.impl.datasource.FakeMediaGalleryDataSource import io.element.android.libraries.mediaviewer.impl.datasource.MediaGalleryDataSource @@ -78,12 +79,13 @@ class MediaViewerPresenterTest { @Test fun `present - initial state null Event`() = runTest { val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + ) ) ) - ) presenter.test { val initialState = awaitFirstItem() assertThat(initialState.listData).isEmpty() @@ -97,13 +99,14 @@ class MediaViewerPresenterTest { @Test fun `present - initial state cannot show info`() = runTest { val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, canShowInfo = false, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + ) ) ) - ) presenter.test { val initialState = awaitFirstItem() assertThat(initialState.listData).isEmpty() @@ -117,13 +120,14 @@ class MediaViewerPresenterTest { @Test fun `present - initial state Event`() = runTest { val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, eventId = AN_EVENT_ID, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + ) ) ) - ) presenter.test { val initialState = awaitFirstItem() assertThat(initialState.listData).isEmpty() @@ -137,14 +141,15 @@ class MediaViewerPresenterTest { @Test fun `present - initial state Event from other`() = runTest { val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, eventId = AN_EVENT_ID, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - sessionId = A_SESSION_ID_2, - canRedactOtherResult = { Result.success(false) }, + sessionId = A_SESSION_ID_2, + canRedactOtherResult = { Result.success(false) }, + ) ) ) - ) presenter.test { val initialState = awaitFirstItem() assertThat(initialState.listData).isEmpty() @@ -161,6 +166,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage() @@ -192,6 +198,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -224,10 +231,13 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, - room = FakeJoinedRoom(baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - )) + room = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + canRedactOwnResult = { Result.success(true) }, + ) + ) ) val anImage = aMediaItemImage( mediaSourceUrl = aUrl, @@ -266,6 +276,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -298,6 +309,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -330,6 +342,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -362,6 +375,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -394,6 +408,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -441,6 +456,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, room = FakeJoinedRoom( liveTimeline = timeline, baseRoom = FakeBaseRoom(canRedactOwnResult = { Result.success(true) }), @@ -498,6 +514,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -549,6 +566,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mode = mode, mediaGalleryDataSource = mediaGalleryDataSource, ) @@ -620,6 +638,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mode = mode, mediaGalleryDataSource = mediaGalleryDataSource, ) @@ -674,6 +693,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) presenter.test { @@ -714,6 +734,7 @@ class MediaViewerPresenterTest { loadMoreLambda = loadMoreLambda, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -744,6 +765,7 @@ class MediaViewerPresenterTest { onViewInTimelineClickLambda = onViewInTimelineClickLambda, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaViewerNavigator = navigator, room = FakeJoinedRoom( baseRoom = FakeBaseRoom(canRedactOwnResult = { Result.success(true) }), @@ -764,42 +786,53 @@ class MediaViewerPresenterTest { private suspend fun ReceiveTurbine.awaitFirstItem(): T { return awaitItem() } - - private fun TestScope.createMediaViewerPresenter( - eventId: EventId? = null, - mode: MediaViewerEntryPoint.MediaViewerMode = MediaViewerEntryPoint.MediaViewerMode.SingleMedia, - matrixMediaLoader: FakeMatrixMediaLoader = FakeMatrixMediaLoader(), - localMediaActions: FakeLocalMediaActions = FakeLocalMediaActions(), - mediaGalleryDataSource: MediaGalleryDataSource = FakeMediaGalleryDataSource( - startLambda = { }, - ), - canShowInfo: Boolean = true, - mediaViewerNavigator: MediaViewerNavigator = FakeMediaViewerNavigator(), - room: JoinedRoom = FakeJoinedRoom( - liveTimeline = FakeTimeline(), - ), - ): MediaViewerPresenter { - return MediaViewerPresenter( - inputs = MediaViewerEntryPoint.Params( - mode = mode, - eventId = eventId, - mediaInfo = TESTED_MEDIA_INFO, - mediaSource = aMediaSource(), - thumbnailSource = null, - canShowInfo = canShowInfo, - ), - navigator = mediaViewerNavigator, - dataSource = MediaViewerDataSource( - mode = mode, - dispatcher = testCoroutineDispatchers().computation, - galleryDataSource = mediaGalleryDataSource, - mediaLoader = matrixMediaLoader, - localMediaFactory = localMediaFactory, - systemClock = FakeSystemClock(), - pagerKeysHandler = PagerKeysHandler(), - ), - room = room, - localMediaActions = localMediaActions, - ) - } } + +internal fun TestScope.createMediaViewerPresenter( + localMediaFactory: LocalMediaFactory, + eventId: EventId? = null, + mode: MediaViewerEntryPoint.MediaViewerMode = MediaViewerEntryPoint.MediaViewerMode.SingleMedia, + matrixMediaLoader: FakeMatrixMediaLoader = FakeMatrixMediaLoader(), + localMediaActions: FakeLocalMediaActions = FakeLocalMediaActions(), + mediaGalleryDataSource: MediaGalleryDataSource = FakeMediaGalleryDataSource( + startLambda = { }, + ), + canShowInfo: Boolean = true, + mediaViewerNavigator: MediaViewerNavigator = FakeMediaViewerNavigator(), + room: JoinedRoom = FakeJoinedRoom( + liveTimeline = FakeTimeline(), + ), +): MediaViewerPresenter { + return MediaViewerPresenter( + inputs = createMediaViewerEntryPointParams( + eventId = eventId, + mode = mode, + canShowInfo = canShowInfo, + ), + navigator = mediaViewerNavigator, + dataSource = MediaViewerDataSource( + mode = mode, + dispatcher = testCoroutineDispatchers().computation, + galleryDataSource = mediaGalleryDataSource, + mediaLoader = matrixMediaLoader, + localMediaFactory = localMediaFactory, + systemClock = FakeSystemClock(), + pagerKeysHandler = PagerKeysHandler(), + ), + room = room, + localMediaActions = localMediaActions, + ) +} + +internal fun createMediaViewerEntryPointParams( + eventId: EventId? = null, + mode: MediaViewerEntryPoint.MediaViewerMode = MediaViewerEntryPoint.MediaViewerMode.SingleMedia, + canShowInfo: Boolean = true, +) = MediaViewerEntryPoint.Params( + mode = mode, + eventId = eventId, + mediaInfo = TESTED_MEDIA_INFO, + mediaSource = aMediaSource(), + thumbnailSource = null, + canShowInfo = canShowInfo, +) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt index 540f107601..c80aa15428 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt @@ -168,7 +168,7 @@ class SingleMediaGalleryDataSourceTest { assertThat(resultData.fileItems).isEmpty() } - private fun aMediaViewerEntryPointParams( + internal fun aMediaViewerEntryPointParams( mediaInfo: MediaInfo, ) = MediaViewerEntryPoint.Params( mode = MediaViewerEntryPoint.MediaViewerMode.SingleMedia, diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt index 83c13bf775..50612c8478 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt @@ -33,7 +33,7 @@ class RoomSelectPresenter( private val dataSource: RoomSelectSearchDataSource, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(mode: RoomSelectMode): RoomSelectPresenter } diff --git a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt new file mode 100644 index 0000000000..c21eede8b8 --- /dev/null +++ b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.roomselect.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.roomselect.api.RoomSelectEntryPoint +import io.element.android.libraries.roomselect.api.RoomSelectMode +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultRoomSelectEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultRoomSelectEntryPoint() + val testMode = RoomSelectMode.Share + val parentNode = TestParentNode.create { buildContext, plugins -> + RoomSelectNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { mode -> + assertThat(mode).isEqualTo(testMode) + createRoomSelectPresenter(mode) + }, + ) + } + val callback = object : RoomSelectEntryPoint.Callback { + override fun onRoomSelected(roomIds: List) = lambdaError() + override fun onCancel() = lambdaError() + } + val params = RoomSelectEntryPoint.Params(testMode) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(RoomSelectNode::class.java) + assertThat(result.plugins).contains(RoomSelectNode.Inputs(params.mode)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt index e8a8e11ca3..8294c97fad 100644 --- a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt +++ b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt @@ -111,15 +111,15 @@ class RoomSelectPresenterTest { cancel() } } - - private fun TestScope.createRoomSelectPresenter( - mode: RoomSelectMode = RoomSelectMode.Forward, - roomListService: RoomListService = FakeRoomListService(), - ) = RoomSelectPresenter( - mode = mode, - dataSource = RoomSelectSearchDataSource( - roomListService = roomListService, - coroutineDispatchers = testCoroutineDispatchers(), - ), - ) } + +internal fun TestScope.createRoomSelectPresenter( + mode: RoomSelectMode = RoomSelectMode.Forward, + roomListService: RoomListService = FakeRoomListService(), +) = RoomSelectPresenter( + mode = mode, + dataSource = RoomSelectSearchDataSource( + roomListService = roomListService, + coroutineDispatchers = testCoroutineDispatchers(), + ), +) diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt new file mode 100644 index 0000000000..9bdbae062f --- /dev/null +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.troubleshoot.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.troubleshoot.api.NotificationTroubleShootEntryPoint +import io.element.android.services.analytics.test.FakeScreenTracker +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultNotificationTroubleShootEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultNotificationTroubleShootEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + TroubleshootNotificationsNode( + buildContext = buildContext, + plugins = plugins, + presenter = createTroubleshootNotificationsPresenter(), + screenTracker = FakeScreenTracker(), + ) + } + val callback = object : NotificationTroubleShootEntryPoint.Callback { + override fun onDone() = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(TroubleshootNotificationsNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt index 4b456fe494..211fa595b5 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt @@ -97,23 +97,23 @@ class TroubleshootNotificationsPresenterTest { assertThat(stateAfterStart.testSuiteState.mainState).isEqualTo(AsyncAction.Loading) } } - - private fun createTroubleshootTestSuite( - tests: Set = emptySet(), - currentPushProvider: String? = null, - ): TroubleshootTestSuite { - return TroubleshootTestSuite( - notificationTroubleshootTests = tests, - getCurrentPushProvider = FakeGetCurrentPushProvider(currentPushProvider), - analyticsService = FakeAnalyticsService(), - ) - } - - private fun createTroubleshootNotificationsPresenter( - troubleshootTestSuite: TroubleshootTestSuite = createTroubleshootTestSuite(), - ): TroubleshootNotificationsPresenter { - return TroubleshootNotificationsPresenter( - troubleshootTestSuite = troubleshootTestSuite, - ) - } +} + +private fun createTroubleshootTestSuite( + tests: Set = emptySet(), + currentPushProvider: String? = null, +): TroubleshootTestSuite { + return TroubleshootTestSuite( + notificationTroubleshootTests = tests, + getCurrentPushProvider = FakeGetCurrentPushProvider(currentPushProvider), + analyticsService = FakeAnalyticsService(), + ) +} + +internal fun createTroubleshootNotificationsPresenter( + troubleshootTestSuite: TroubleshootTestSuite = createTroubleshootTestSuite(), +): TroubleshootNotificationsPresenter { + return TroubleshootNotificationsPresenter( + troubleshootTestSuite = troubleshootTestSuite, + ) } diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt new file mode 100644 index 0000000000..9fb0e50309 --- /dev/null +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.troubleshoot.impl.history + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.push.test.FakePushService +import io.element.android.libraries.troubleshoot.api.PushHistoryEntryPoint +import io.element.android.services.analytics.test.FakeScreenTracker +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultPushHistoryEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultPushHistoryEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + PushHistoryNode( + buildContext = buildContext, + plugins = plugins, + presenter = PushHistoryPresenter( + pushService = FakePushService(), + ), + screenTracker = FakeScreenTracker(), + ) + } + val callback = object : PushHistoryEntryPoint.Callback { + override fun onDone() = lambdaError() + override fun onItemClick(sessionId: SessionId, roomId: RoomId, eventId: EventId) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(PushHistoryNode::class.java) + assertThat(result.plugins).contains(callback) + } +} From bebde0e9dd0647e6fea5ce68271d1575d94ac4c9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Sep 2025 22:53:04 +0200 Subject: [PATCH 066/145] Cleanup --- features/analytics/impl/build.gradle.kts | 2 +- .../features/logout/impl/AccountDeactivationPresenterTest.kt | 1 - .../invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt | 1 - .../features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt | 1 - .../impl/DefaultRoomAliasResolverEntryPointTest.kt | 1 - .../android/features/signedout/impl/SignedOutPresenterTest.kt | 2 +- .../features/startchat/impl/DefaultStartChatEntryPointTest.kt | 1 - .../io/element/android/tests/testutils/node/TestParentNode.kt | 1 - 8 files changed, 2 insertions(+), 8 deletions(-) diff --git a/features/analytics/impl/build.gradle.kts b/features/analytics/impl/build.gradle.kts index d35db4295e..ddf093d9c3 100644 --- a/features/analytics/impl/build.gradle.kts +++ b/features/analytics/impl/build.gradle.kts @@ -1,5 +1,5 @@ -import extension.testCommonDependencies import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt index e8edea3ab6..d0b9f57dd9 100644 --- a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt @@ -148,7 +148,6 @@ class AccountDeactivationPresenterTest { assertThat(finalState2.accountDeactivationAction).isEqualTo(AsyncAction.Uninitialized) } } - } internal fun createPresenter( diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt index ae8893f829..651b7bb6bb 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt @@ -16,7 +16,6 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.test.A_ROOM_ID -import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaRecorder diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt index aa81b0c51b..c16011229a 100644 --- a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt @@ -37,7 +37,6 @@ class DefaultJoinRoomEntryPointTest { declineAndBlockEntryPoint = object : DeclineInviteAndBlockEntryPoint { override fun createNode(parentNode: Node, buildContext: BuildContext, inviteData: InviteData) = lambdaError() } - ) } val inputs = JoinRoomEntryPoint.Inputs( diff --git a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt index efd25c60df..45762956c6 100644 --- a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt +++ b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt @@ -33,7 +33,6 @@ class DefaultRoomAliasResolverEntryPointTest { alias, ) } - ) } val callback = object : RoomAliasResolverEntryPoint.Callback { diff --git a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt index d3a52c8b37..67f307af03 100644 --- a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt +++ b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt @@ -22,7 +22,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -private val appName = "AppName" +private const val appName = "AppName" class SignedOutPresenterTest { @get:Rule diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt index 351ccb651a..fbc027e3e2 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt @@ -13,7 +13,6 @@ import com.bumble.appyx.core.node.Node import com.google.common.truth.Truth.assertThat import io.element.android.features.createroom.api.CreateRoomEntryPoint import io.element.android.features.startchat.api.StartChatEntryPoint -import io.element.android.features.startchat.impl.root.StartChatNode import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/node/TestParentNode.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/node/TestParentNode.kt index a0183e8755..79def028f7 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/node/TestParentNode.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/node/TestParentNode.kt @@ -30,7 +30,6 @@ class TestParentNode( plugins = emptyList(), view = EmptyNodeView, ) { - override val graph: NodeFactoriesBindings = NodeFactoriesBindings { mapOf( childNodeClass to AssistedNodeFactory { buildContext, plugins -> From 86dca3f04b41e443dc8162a4bded7e5199afa1b5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Sep 2025 23:28:23 +0200 Subject: [PATCH 067/145] Cleanup --- .../features/signedout/impl/SignedOutPresenterTest.kt | 7 +++---- .../io/element/android/libraries/matrix/test/TestData.kt | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt index 67f307af03..de5634f269 100644 --- a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt +++ b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt @@ -12,6 +12,7 @@ import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.test.AN_APPLICATION_NAME import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.sessionstorage.api.SessionStore @@ -22,8 +23,6 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -private const val appName = "AppName" - class SignedOutPresenterTest { @get:Rule val warmUpRule = WarmUpRule() @@ -40,7 +39,7 @@ class SignedOutPresenterTest { }.test { skipItems(1) val initialState = awaitItem() - assertThat(initialState.appName).isEqualTo(appName) + assertThat(initialState.appName).isEqualTo(AN_APPLICATION_NAME) assertThat(initialState.signedOutSession).isEqualTo(aSessionData) } } @@ -73,6 +72,6 @@ internal fun createSignedOutPresenter( return SignedOutPresenter( sessionId = sessionId.value, sessionStore = sessionStore, - buildMeta = aBuildMeta(applicationName = appName), + buildMeta = aBuildMeta(applicationName = AN_APPLICATION_NAME), ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt index a63c301ce0..ca0db64285 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt @@ -25,6 +25,7 @@ const val A_USER_NAME_2 = "Bob" const val A_PASSWORD = "password" const val A_PASSPHRASE = "passphrase" const val A_SECRET = "secret" +const val AN_APPLICATION_NAME = "AppName" val A_USER_ID = UserId("@alice:server.org") val A_USER_ID_2 = UserId("@bob:server.org") From 4b65d5cf9a600832a857526fbf343bbefb5a0deb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Sat, 13 Sep 2025 00:05:23 +0200 Subject: [PATCH 068/145] Remove dead code. --- .../android/libraries/architecture/NodeFactories.kt | 11 +---------- .../matrix/api/user/CurrentSessionIdHolder.kt | 3 --- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt index 0a3c3c4433..63cb4c4ed9 100644 --- a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt @@ -7,7 +7,6 @@ package io.element.android.libraries.architecture -import android.content.Context import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin @@ -22,17 +21,9 @@ inline fun Node.createNode( return bindings.createNode(buildContext, plugins) } -inline fun Context.createNode( - buildContext: BuildContext, - plugins: List = emptyList() -): N { - val bindings: NodeFactoriesBindings = bindings() - return bindings.createNode(buildContext, plugins) -} - inline fun NodeFactoriesBindings.createNode( buildContext: BuildContext, - plugins: List = emptyList() + plugins: List, ): N { val nodeClass = N::class val nodeFactoryMap = nodeFactories() diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/CurrentSessionIdHolder.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/CurrentSessionIdHolder.kt index b5a42fb9c3..171f8337e0 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/CurrentSessionIdHolder.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/CurrentSessionIdHolder.kt @@ -11,12 +11,9 @@ import dev.zacsweers.metro.Inject import dev.zacsweers.metro.SingleIn import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient -import io.element.android.libraries.matrix.api.core.SessionId @SingleIn(SessionScope::class) @Inject class CurrentSessionIdHolder(matrixClient: MatrixClient) { val current = matrixClient.sessionId - - fun isCurrentSession(sessionId: SessionId?): Boolean = current == sessionId } From cca195a1a5000601ac7a4531a352b5c33e121666 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Sat, 13 Sep 2025 00:14:57 +0200 Subject: [PATCH 069/145] Add more tests. --- .../impl/DefaultLockScreenEntryPointTest.kt | 9 +++++++++ .../messages/impl/DefaultMessagesEntryPointTest.kt | 8 ++++++++ .../impl/DefaultPreferencesEntryPointTest.kt | 7 +++++++ .../impl/DefaultRoomDetailsEntryPointTest.kt | 11 +++++++++++ 4 files changed, 35 insertions(+) diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt index 854e89b13a..c74366ef46 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt @@ -8,9 +8,11 @@ package io.element.android.features.lockscreen.impl import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.lockscreen.api.LockScreenEntryPoint +import io.element.android.features.lockscreen.impl.unlock.activity.PinUnlockActivity import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import org.junit.Test @@ -59,4 +61,11 @@ class DefaultLockScreenEntryPointTest { assertThat(result.plugins).contains(LockScreenFlowNode.Inputs(LockScreenFlowNode.NavTarget.Settings)) assertThat(result.plugins).contains(callback) } + + @Test + fun `test pin unlock intent`() { + val entryPoint = DefaultLockScreenEntryPoint() + val result = entryPoint.pinUnlockIntent(InstrumentationRegistry.getInstrumentation().context) + assertThat(result.component?.className).isEqualTo(PinUnlockActivity::class.qualifiedName) + } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt index dd4f4e4d41..fa3896aeea 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt @@ -118,4 +118,12 @@ class DefaultMessagesEntryPointTest { assertThat(result.plugins).contains(MessagesEntryPoint.Params(initialTarget)) assertThat(result.plugins).contains(callback) } + + @Test + fun `test initial target to nav target mapping`() { + assertThat(MessagesEntryPoint.InitialTarget.Messages(focusedEventId = AN_EVENT_ID).toNavTarget()) + .isEqualTo(MessagesFlowNode.NavTarget.Messages(AN_EVENT_ID)) + assertThat(MessagesEntryPoint.InitialTarget.PinnedMessages.toNavTarget()) + .isEqualTo(MessagesFlowNode.NavTarget.PinnedMessagesList) + } } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt index 971ca6ab51..9ef0e09512 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt @@ -74,4 +74,11 @@ class DefaultPreferencesEntryPointTest { assertThat(result.plugins).contains(params) assertThat(result.plugins).contains(callback) } + + @Test + fun `test initial target to nav target mapping`() { + assertThat(PreferencesEntryPoint.InitialTarget.Root.toNavTarget()).isEqualTo(PreferencesFlowNode.NavTarget.Root) + assertThat(PreferencesEntryPoint.InitialTarget.NotificationSettings.toNavTarget()).isEqualTo(PreferencesFlowNode.NavTarget.NotificationSettings) + assertThat(PreferencesEntryPoint.InitialTarget.NotificationTroubleshoot.toNavTarget()).isEqualTo(PreferencesFlowNode.NavTarget.TroubleshootNotifications) + } } diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt index e863b7b562..0115fd9c44 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt @@ -24,6 +24,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkData +import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint @@ -102,4 +103,14 @@ class DefaultRoomDetailsEntryPointTest { assertThat(result.plugins).contains(params) assertThat(result.plugins).contains(callback) } + + @Test + fun `test initial target to nav target mapping`() { + assertThat(RoomDetailsEntryPoint.InitialTarget.RoomDetails.toNavTarget()) + .isEqualTo(RoomDetailsFlowNode.NavTarget.RoomDetails) + assertThat(RoomDetailsEntryPoint.InitialTarget.RoomMemberDetails(A_USER_ID).toNavTarget()) + .isEqualTo(RoomDetailsFlowNode.NavTarget.RoomMemberDetails(A_USER_ID)) + assertThat(RoomDetailsEntryPoint.InitialTarget.RoomNotificationSettings.toNavTarget()) + .isEqualTo(RoomDetailsFlowNode.NavTarget.RoomNotificationSettings(showUserDefinedSettingStyle = true)) + } } From c90332bb6e8bd61b4b36249124dafd98225a2503 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Sat, 13 Sep 2025 00:54:44 +0200 Subject: [PATCH 070/145] Split long line --- .../preferences/impl/DefaultPreferencesEntryPointTest.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt index 9ef0e09512..725ef02b5d 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt @@ -77,8 +77,11 @@ class DefaultPreferencesEntryPointTest { @Test fun `test initial target to nav target mapping`() { - assertThat(PreferencesEntryPoint.InitialTarget.Root.toNavTarget()).isEqualTo(PreferencesFlowNode.NavTarget.Root) - assertThat(PreferencesEntryPoint.InitialTarget.NotificationSettings.toNavTarget()).isEqualTo(PreferencesFlowNode.NavTarget.NotificationSettings) - assertThat(PreferencesEntryPoint.InitialTarget.NotificationTroubleshoot.toNavTarget()).isEqualTo(PreferencesFlowNode.NavTarget.TroubleshootNotifications) + assertThat(PreferencesEntryPoint.InitialTarget.Root.toNavTarget()) + .isEqualTo(PreferencesFlowNode.NavTarget.Root) + assertThat(PreferencesEntryPoint.InitialTarget.NotificationSettings.toNavTarget()) + .isEqualTo(PreferencesFlowNode.NavTarget.NotificationSettings) + assertThat(PreferencesEntryPoint.InitialTarget.NotificationTroubleshoot.toNavTarget()) + .isEqualTo(PreferencesFlowNode.NavTarget.TroubleshootNotifications) } } From 4d7d0ac8d099eae85b86877df60bc6ce6af2b0b5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Sep 2025 10:49:13 +0200 Subject: [PATCH 071/145] Avoid using AndroidJUnit4 runner to test Entrypoint implementations. --- appnav/build.gradle.kts | 2 -- .../impl/DefaultAnalyticsEntryPointTest.kt | 8 +++--- .../impl/DefaultCreateRoomEntryPointTest.kt | 12 ++++++--- ...efaultAccountDeactivationEntryPointTest.kt | 8 +++--- .../ftue/impl/DefaultFtueEntryPointTest.kt | 12 ++++++--- .../DefaultDeclineAndBlockEntryPointTest.kt | 8 +++--- .../impl/DefaultJoinRoomEntryPointTest.kt | 12 ++++++--- .../DefaultKnockRequestsListEntryPointTest.kt | 8 +++--- ...efaultOpenSourcesLicensesEntryPointTest.kt | 12 ++++++--- .../send/DefaultSendLocationEntryPointTest.kt | 8 +++--- .../show/DefaultShowLocationEntryPointTest.kt | 8 +++--- .../DefaultLockScreenEntryPointIntentTest.kt | 25 +++++++++++++++++++ .../impl/DefaultLockScreenEntryPointTest.kt | 21 +++++++--------- .../login/impl/DefaultLoginEntryPointTest.kt | 12 ++++++--- .../impl/DefaultLogoutEntryPointTest.kt | 8 +++--- .../impl/DefaultMessagesEntryPointTest.kt | 12 ++++++--- .../create/DefaultCreatePollEntryPointTest.kt | 8 +++--- .../DefaultPollHistoryEntryPointTest.kt | 12 ++++++--- .../impl/DefaultPreferencesEntryPointTest.kt | 12 ++++++--- .../DefaultBugReportEntryPointTest.kt | 8 +++--- .../impl/DefaultReportRoomEntryPointTest.kt | 8 +++--- .../DefaultRoomAliasResolverEntryPointTest.kt | 8 +++--- .../impl/DefaultRoomDetailsEntryPointTest.kt | 12 ++++++--- .../DefaultRoomDirectoryEntryPointTest.kt | 8 +++--- .../impl/DefaultSecureBackupEntryPointTest.kt | 12 ++++++--- .../share/impl/DefaultShareEntryPointTest.kt | 12 ++++++--- .../impl/DefaultSignedOutEntryPointTest.kt | 8 +++--- .../space/impl/DefaultSpaceEntryPointTest.kt | 8 +++--- .../impl/DefaultStartChatEntryPointTest.kt | 12 ++++++--- .../impl/DefaultUserProfileEntryPointTest.kt | 12 ++++++--- ...faultIncomingVerificationEntryPointTest.kt | 8 +++--- ...faultOutgoingVerificationEntryPointTest.kt | 8 +++--- .../impl/DefaultViewFolderEntryPointTest.kt | 12 ++++++--- .../impl/DefaultMediaGalleryEntryPointTest.kt | 12 ++++++--- .../impl/DefaultMediaViewerEntryPointTest.kt | 8 +++--- .../impl/DefaultRoomSelectEntryPointTest.kt | 8 +++--- ...tNotificationTroubleShootEntryPointTest.kt | 8 +++--- .../DefaultPushHistoryEntryPointTest.kt | 8 +++--- .../kotlin/extension/DependencyHandleScope.kt | 2 ++ 39 files changed, 271 insertions(+), 119 deletions(-) create mode 100644 features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointIntentTest.kt diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index f91a194e04..ef97f92781 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -61,6 +61,4 @@ dependencies { testImplementation(projects.services.appnavstate.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.toolbox.test) - testImplementation(libs.test.appyx.junit) - testImplementation(libs.test.arch.core) } diff --git a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/DefaultAnalyticsEntryPointTest.kt b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/DefaultAnalyticsEntryPointTest.kt index a814332994..b5ec819632 100644 --- a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/DefaultAnalyticsEntryPointTest.kt +++ b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/DefaultAnalyticsEntryPointTest.kt @@ -7,17 +7,19 @@ package io.element.android.features.analytics.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultAnalyticsEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node creation`() { val entryPoint = DefaultAnalyticsEntryPoint() diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt index 6c6790adff..61c7c052c5 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt @@ -7,18 +7,24 @@ package io.element.android.features.createroom.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.createroom.api.CreateRoomEntryPoint import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultCreateRoomEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultCreateRoomEntryPoint() diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt index e055b4a979..05ad52efe9 100644 --- a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt @@ -7,15 +7,17 @@ package io.element.android.features.logout.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultAccountDeactivationEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultAccountDeactivationEntryPoint() diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt index 3a4a2ea334..e3f0d7b2a6 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt @@ -9,19 +9,25 @@ package io.element.android.features.ftue.impl import android.content.Context import android.content.Intent -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.lockscreen.api.LockScreenEntryPoint import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultFtueEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultFtueEntryPoint() diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt index a3016a785c..7cdf208b9a 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt @@ -7,16 +7,18 @@ package io.element.android.features.invite.impl.declineandblock -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.invite.test.anInviteData import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultDeclineAndBlockEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultDeclineAndBlockEntryPoint() diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt index c16011229a..af75fd528c 100644 --- a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt @@ -7,9 +7,10 @@ package io.element.android.features.joinroom.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.JoinedRoom import io.element.android.features.invite.api.InviteData @@ -19,12 +20,17 @@ import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith import java.util.Optional -@RunWith(AndroidJUnit4::class) class DefaultJoinRoomEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultJoinRoomEntryPoint() diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt index 2a4196da9b..b6b6d766c7 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt @@ -7,16 +7,18 @@ package io.element.android.features.knockrequests.impl.list -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultKnockRequestsListEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultKnockRequestsListEntryPoint() diff --git a/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt b/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt index 730760cb93..abd6c5e23e 100644 --- a/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt +++ b/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt @@ -7,15 +7,21 @@ package io.element.android.features.licenses.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultOpenSourcesLicensesEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultOpenSourcesLicensesEntryPoint() diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt index 705d2a293c..9be79c7092 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt @@ -7,7 +7,7 @@ package io.element.android.features.location.impl.send -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.location.impl.common.actions.FakeLocationActions @@ -18,11 +18,13 @@ import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultSendLocationEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultSendLocationEntryPoint() diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt index 046f286550..d31ef0c0e4 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt @@ -7,7 +7,7 @@ package io.element.android.features.location.impl.show -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.location.api.Location @@ -17,11 +17,13 @@ import io.element.android.features.location.impl.common.permissions.FakePermissi import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultShowLocationEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultShowLocationEntryPoint() diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointIntentTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointIntentTest.kt new file mode 100644 index 0000000000..995140b87b --- /dev/null +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointIntentTest.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.lockscreen.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.google.common.truth.Truth.assertThat +import io.element.android.features.lockscreen.impl.unlock.activity.PinUnlockActivity +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultLockScreenEntryPointIntentTest { + @Test + fun `test pin unlock intent`() { + val entryPoint = DefaultLockScreenEntryPoint() + val result = entryPoint.pinUnlockIntent(InstrumentationRegistry.getInstrumentation().context) + assertThat(result.component?.className).isEqualTo(PinUnlockActivity::class.qualifiedName) + } +} diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt index c74366ef46..822d275063 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt @@ -7,19 +7,23 @@ package io.element.android.features.lockscreen.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.lockscreen.api.LockScreenEntryPoint -import io.element.android.features.lockscreen.impl.unlock.activity.PinUnlockActivity import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultLockScreenEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder Setup`() { val entryPoint = DefaultLockScreenEntryPoint() @@ -61,11 +65,4 @@ class DefaultLockScreenEntryPointTest { assertThat(result.plugins).contains(LockScreenFlowNode.Inputs(LockScreenFlowNode.NavTarget.Settings)) assertThat(result.plugins).contains(callback) } - - @Test - fun `test pin unlock intent`() { - val entryPoint = DefaultLockScreenEntryPoint() - val result = entryPoint.pinUnlockIntent(InstrumentationRegistry.getInstrumentation().context) - assertThat(result.component?.className).isEqualTo(PinUnlockActivity::class.qualifiedName) - } } diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt index 6b44f836b6..c10d22c51a 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt @@ -7,8 +7,9 @@ package io.element.android.features.login.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.login.api.LoginEntryPoint @@ -16,11 +17,16 @@ import io.element.android.features.login.impl.accountprovider.AccountProviderDat import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultLoginEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultLoginEntryPoint() diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt index 86300353b0..01d1bfc6ca 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt @@ -7,17 +7,19 @@ package io.element.android.features.logout.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.logout.api.LogoutEntryPoint import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultLogoutEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultLogoutEntryPoint() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt index fa3896aeea..cf98370ddc 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt @@ -7,10 +7,11 @@ package io.element.android.features.messages.impl +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.compose.runtime.Composable -import androidx.test.ext.junit.runners.AndroidJUnit4 import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.call.api.CallType import io.element.android.features.call.api.ElementCallEntryPoint @@ -42,11 +43,16 @@ import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultMessagesEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultMessagesEntryPoint() diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt index 2150292c4c..bf77cb4535 100644 --- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt @@ -7,7 +7,7 @@ package io.element.android.features.poll.impl.create -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.test.FakeMessageComposerContext @@ -19,11 +19,13 @@ import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.timeline.LiveTimelineProvider import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultCreatePollEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultCreatePollEntryPoint() diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt index 6d9e44a8a2..dfab33e837 100644 --- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt @@ -7,19 +7,25 @@ package io.element.android.features.poll.impl.history -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.poll.api.create.CreatePollEntryPoint import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultPollHistoryEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultPollHistoryEntryPoint() diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt index 725ef02b5d..b7ebb08f3a 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt @@ -8,9 +8,10 @@ package io.element.android.features.preferences.impl import android.content.Context -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.deactivation.api.AccountDeactivationEntryPoint import io.element.android.features.licenses.api.OpenSourceLicensesEntryPoint @@ -24,11 +25,16 @@ import io.element.android.libraries.troubleshoot.api.NotificationTroubleShootEnt import io.element.android.libraries.troubleshoot.api.PushHistoryEntryPoint import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultPreferencesEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultPreferencesEntryPoint() diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt index 5ea1bb23db..d76e8edb50 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt @@ -7,18 +7,20 @@ package io.element.android.features.rageshake.impl.bugreport -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultBugReportEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultBugReportEntryPoint() diff --git a/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt index c8d5998149..c9f850062e 100644 --- a/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt +++ b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt @@ -7,16 +7,18 @@ package io.element.android.features.reportroom.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultReportRoomEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultReportRoomEntryPoint() diff --git a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt index 45762956c6..238b35017b 100644 --- a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt +++ b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt @@ -7,7 +7,7 @@ package io.element.android.features.roomaliasresolver.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.roomaliasesolver.api.RoomAliasResolverEntryPoint @@ -15,11 +15,13 @@ import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultRoomAliasResolverEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultRoomAliasResolverEntryPoint() diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt index 0115fd9c44..3c29ef5c2e 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt @@ -7,9 +7,10 @@ package io.element.android.features.roomdetails.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.call.api.CallType import io.element.android.features.call.api.ElementCallEntryPoint @@ -31,11 +32,16 @@ import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultRoomDetailsEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultRoomDetailsEntryPoint() diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt index fc3ffa2ec3..d544f55000 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt @@ -7,7 +7,7 @@ package io.element.android.features.roomdirectory.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.roomdirectory.api.RoomDescription @@ -17,11 +17,13 @@ import io.element.android.features.roomdirectory.impl.root.createRoomDirectoryPr import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultRoomDirectoryEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultRoomDirectoryEntryPoint() diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt index 13a00ff046..7741b5141a 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt @@ -7,17 +7,23 @@ package io.element.android.features.securebackup.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.securebackup.api.SecureBackupEntryPoint import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultSecureBackupEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultSecureBackupEntryPoint() diff --git a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt index 2762af89c7..66ee853d26 100644 --- a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt +++ b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt @@ -8,9 +8,10 @@ package io.element.android.features.share.impl import android.content.Intent -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.share.api.ShareEntryPoint import io.element.android.libraries.matrix.api.core.RoomId @@ -18,11 +19,16 @@ import io.element.android.libraries.roomselect.api.RoomSelectEntryPoint import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultShareEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultShareEntryPoint() diff --git a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt index 0edcbf2054..860ad88d8a 100644 --- a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt +++ b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt @@ -7,17 +7,19 @@ package io.element.android.features.signedout.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.signedout.api.SignedOutEntryPoint import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultSignedOutEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultSignedOutEntryPoint() diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt index f57ee5cafb..465fde3425 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt @@ -7,7 +7,7 @@ package io.element.android.features.space.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.invite.test.InMemorySeenInvitesStore @@ -19,11 +19,13 @@ import io.element.android.libraries.matrix.test.spaces.FakeSpaceRoomList import io.element.android.libraries.matrix.test.spaces.FakeSpaceService import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultSpaceEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultSpaceEntryPoint() diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt index fbc027e3e2..8f4a41a3fa 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt @@ -7,20 +7,26 @@ package io.element.android.features.startchat.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.createroom.api.CreateRoomEntryPoint import io.element.android.features.startchat.api.StartChatEntryPoint import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultStartChatEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultStartChatEntryPoint() diff --git a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt index 266d709ccf..dbe5ed89f1 100644 --- a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt +++ b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt @@ -7,9 +7,10 @@ package io.element.android.features.userprofile.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.call.api.CallType import io.element.android.features.call.api.ElementCallEntryPoint @@ -24,11 +25,16 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultUserProfileEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultUserProfileEntryPoint() diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt index b3ac839b54..ad586fc7fb 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt @@ -7,18 +7,20 @@ package io.element.android.features.verifysession.impl.incoming -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.verifysession.api.IncomingVerificationEntryPoint import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultIncomingVerificationEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultIncomingVerificationEntryPoint() diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt index f4b53a133c..52ff36dbd6 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt @@ -7,17 +7,19 @@ package io.element.android.features.verifysession.impl.outgoing -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.verifysession.api.OutgoingVerificationEntryPoint import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultOutgoingVerificationEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultOutgoingVerificationEntryPoint() diff --git a/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt b/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt index dc2431c986..752c1f93d0 100644 --- a/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt +++ b/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt @@ -7,18 +7,24 @@ package io.element.android.features.viewfolder.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.viewfolder.api.ViewFolderEntryPoint import io.element.android.features.viewfolder.impl.root.ViewFolderRootNode import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultViewFolderEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultViewFolderEntryPoint() diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt index 27dc68e75e..27bf059199 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt @@ -7,9 +7,10 @@ package io.element.android.libraries.mediaviewer.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint @@ -17,11 +18,16 @@ import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.impl.gallery.root.MediaGalleryRootNode import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultMediaGalleryEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() { val entryPoint = DefaultMediaGalleryEntryPoint() diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt index 90ff2f4e70..3af2e8cf69 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt @@ -8,7 +8,7 @@ package io.element.android.libraries.mediaviewer.impl import android.net.Uri -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.libraries.core.mimetype.MimeTypes @@ -31,11 +31,13 @@ import io.element.android.tests.testutils.node.TestParentNode import io.element.android.tests.testutils.testCoroutineDispatchers import io.mockk.mockk import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultMediaViewerEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultMediaViewerEntryPoint() diff --git a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt index c21eede8b8..bb9c15e7e6 100644 --- a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt +++ b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt @@ -7,7 +7,7 @@ package io.element.android.libraries.roomselect.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.RoomId @@ -16,11 +16,13 @@ import io.element.android.libraries.roomselect.api.RoomSelectMode import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultRoomSelectEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultRoomSelectEntryPoint() diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt index 9bdbae062f..d9bf607531 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt @@ -7,18 +7,20 @@ package io.element.android.libraries.troubleshoot.impl -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.libraries.troubleshoot.api.NotificationTroubleShootEntryPoint import io.element.android.services.analytics.test.FakeScreenTracker import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultNotificationTroubleShootEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultNotificationTroubleShootEntryPoint() diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt index 9fb0e50309..3604622f5c 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt @@ -7,7 +7,7 @@ package io.element.android.libraries.troubleshoot.impl.history -import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.EventId @@ -18,11 +18,13 @@ import io.element.android.libraries.troubleshoot.api.PushHistoryEntryPoint import io.element.android.services.analytics.test.FakeScreenTracker import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -@RunWith(AndroidJUnit4::class) class DefaultPushHistoryEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + @Test fun `test node builder`() { val entryPoint = DefaultPushHistoryEntryPoint() diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index af87cffb99..2b6c531eda 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -44,6 +44,8 @@ fun DependencyHandlerScope.testCommonDependencies( testImplementation(libs.androidx.test.ext.junit) testImplementation(libs.coroutines.test) testImplementation(libs.molecule.runtime) + testImplementation(libs.test.appyx.junit) + testImplementation(libs.test.arch.core) testImplementation(libs.test.junit) testImplementation(libs.test.mockk) testImplementation(libs.test.robolectric) From 574c2cb2b5a3f1aa00a731c19ac50ad956c83f70 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Sep 2025 12:20:52 +0200 Subject: [PATCH 072/145] Remove empty line. --- .../fileTemplates/Template Module Feature Entry Point API.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/templates/files/fileTemplates/Template Module Feature Entry Point API.kt b/tools/templates/files/fileTemplates/Template Module Feature Entry Point API.kt index 6297ec4e24..37f0500444 100644 --- a/tools/templates/files/fileTemplates/Template Module Feature Entry Point API.kt +++ b/tools/templates/files/fileTemplates/Template Module Feature Entry Point API.kt @@ -6,7 +6,6 @@ import com.bumble.appyx.core.plugin.Plugin import io.element.android.libraries.architecture.FeatureEntryPoint interface ${FEATURE_NAME}EntryPoint : FeatureEntryPoint { - fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder interface NodeBuilder { From 1dd67ca945329002dd60c0e7fcb87d9c6be5af2f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Sep 2025 12:20:44 +0200 Subject: [PATCH 073/145] Use SimpleFeatureEntryPoint when possible. --- .../io/element/android/appnav/LoggedInFlowNode.kt | 3 +-- .../android/features/ftue/api/FtueEntryPoint.kt | 12 ++---------- .../features/ftue/impl/DefaultFtueEntryPoint.kt | 11 ++--------- .../features/ftue/impl/DefaultFtueEntryPointTest.kt | 3 +-- .../licenses/api/OpenSourceLicensesEntryPoint.kt | 7 ++----- .../impl/DefaultOpenSourcesLicensesEntryPoint.kt | 4 ++-- .../impl/DefaultOpenSourcesLicensesEntryPointTest.kt | 2 +- .../poll/api/history/PollHistoryEntryPoint.kt | 8 ++------ .../features/preferences/impl/PreferencesFlowNode.kt | 2 +- .../impl/DefaultPreferencesEntryPointTest.kt | 2 +- 10 files changed, 15 insertions(+), 39 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index 97fff8ee5c..1577bbbd40 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -454,8 +454,7 @@ class LoggedInFlowNode( .build() } NavTarget.Ftue -> { - ftueEntryPoint.nodeBuilder(this, buildContext) - .build() + ftueEntryPoint.createNode(this, buildContext) } NavTarget.RoomDirectorySearch -> { roomDirectoryEntryPoint.nodeBuilder(this, buildContext) diff --git a/features/ftue/api/src/main/kotlin/io/element/android/features/ftue/api/FtueEntryPoint.kt b/features/ftue/api/src/main/kotlin/io/element/android/features/ftue/api/FtueEntryPoint.kt index f719064fde..3d5aae3860 100644 --- a/features/ftue/api/src/main/kotlin/io/element/android/features/ftue/api/FtueEntryPoint.kt +++ b/features/ftue/api/src/main/kotlin/io/element/android/features/ftue/api/FtueEntryPoint.kt @@ -7,14 +7,6 @@ package io.element.android.features.ftue.api -import com.bumble.appyx.core.modality.BuildContext -import com.bumble.appyx.core.node.Node -import io.element.android.libraries.architecture.FeatureEntryPoint +import io.element.android.libraries.architecture.SimpleFeatureEntryPoint -interface FtueEntryPoint : FeatureEntryPoint { - fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder - - interface NodeBuilder { - fun build(): Node - } -} +interface FtueEntryPoint : SimpleFeatureEntryPoint diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPoint.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPoint.kt index db3c6a9c91..4fa086f4cd 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPoint.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPoint.kt @@ -9,7 +9,6 @@ package io.element.android.features.ftue.impl import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node -import com.bumble.appyx.core.plugin.Plugin import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Inject @@ -19,13 +18,7 @@ import io.element.android.libraries.architecture.createNode @ContributesBinding(AppScope::class) @Inject class DefaultFtueEntryPoint : FtueEntryPoint { - override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): FtueEntryPoint.NodeBuilder { - val plugins = ArrayList() - - return object : FtueEntryPoint.NodeBuilder { - override fun build(): Node { - return parentNode.createNode(buildContext, plugins) - } - } + override fun createNode(parentNode: Node, buildContext: BuildContext): Node { + return parentNode.createNode(buildContext) } } diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt index e3f0d7b2a6..50cc2eadce 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt @@ -53,8 +53,7 @@ class DefaultFtueEntryPointTest { }, ) } - val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) - .build() + val result = entryPoint.createNode(parentNode, BuildContext.root(null)) assertThat(result).isInstanceOf(FtueFlowNode::class.java) } } diff --git a/features/licenses/api/src/main/kotlin/io/element/android/features/licenses/api/OpenSourceLicensesEntryPoint.kt b/features/licenses/api/src/main/kotlin/io/element/android/features/licenses/api/OpenSourceLicensesEntryPoint.kt index e4beebe6ef..a2dbdde60d 100644 --- a/features/licenses/api/src/main/kotlin/io/element/android/features/licenses/api/OpenSourceLicensesEntryPoint.kt +++ b/features/licenses/api/src/main/kotlin/io/element/android/features/licenses/api/OpenSourceLicensesEntryPoint.kt @@ -7,9 +7,6 @@ package io.element.android.features.licenses.api -import com.bumble.appyx.core.modality.BuildContext -import com.bumble.appyx.core.node.Node +import io.element.android.libraries.architecture.SimpleFeatureEntryPoint -interface OpenSourceLicensesEntryPoint { - fun getNode(node: Node, buildContext: BuildContext): Node -} +interface OpenSourceLicensesEntryPoint : SimpleFeatureEntryPoint diff --git a/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPoint.kt b/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPoint.kt index 425346a90e..8ffbc05ed3 100644 --- a/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPoint.kt +++ b/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPoint.kt @@ -18,7 +18,7 @@ import io.element.android.libraries.architecture.createNode @ContributesBinding(AppScope::class) @Inject class DefaultOpenSourcesLicensesEntryPoint : OpenSourceLicensesEntryPoint { - override fun getNode(node: Node, buildContext: BuildContext): Node { - return node.createNode(buildContext) + override fun createNode(parentNode: Node, buildContext: BuildContext): Node { + return parentNode.createNode(buildContext) } } diff --git a/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt b/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt index abd6c5e23e..3209e28fe6 100644 --- a/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt +++ b/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt @@ -31,7 +31,7 @@ class DefaultOpenSourcesLicensesEntryPointTest { plugins = plugins, ) } - val result = entryPoint.getNode(parentNode, BuildContext.root(null)) + val result = entryPoint.createNode(parentNode, BuildContext.root(null)) assertThat(result).isInstanceOf(DependenciesFlowNode::class.java) } } diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/history/PollHistoryEntryPoint.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/history/PollHistoryEntryPoint.kt index 7ca61340c4..49f5f92b87 100644 --- a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/history/PollHistoryEntryPoint.kt +++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/history/PollHistoryEntryPoint.kt @@ -7,10 +7,6 @@ package io.element.android.features.poll.api.history -import com.bumble.appyx.core.modality.BuildContext -import com.bumble.appyx.core.node.Node -import io.element.android.libraries.architecture.FeatureEntryPoint +import io.element.android.libraries.architecture.SimpleFeatureEntryPoint -interface PollHistoryEntryPoint : FeatureEntryPoint { - fun createNode(parentNode: Node, buildContext: BuildContext): Node -} +interface PollHistoryEntryPoint : SimpleFeatureEntryPoint diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index 6b0d8a7bec..57643e3931 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -261,7 +261,7 @@ class PreferencesFlowNode( .build() } is NavTarget.OssLicenses -> { - openSourceLicensesEntryPoint.getNode(this, buildContext) + openSourceLicensesEntryPoint.createNode(this, buildContext) } NavTarget.AccountDeactivation -> { accountDeactivationEntryPoint.createNode(this, buildContext) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt index b7ebb08f3a..807ff3a5c6 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt @@ -56,7 +56,7 @@ class DefaultPreferencesEntryPointTest { override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() }, openSourceLicensesEntryPoint = object : OpenSourceLicensesEntryPoint { - override fun getNode(node: Node, buildContext: BuildContext) = lambdaError() + override fun createNode(parentNode: Node, buildContext: BuildContext) = lambdaError() }, accountDeactivationEntryPoint = object : AccountDeactivationEntryPoint { override fun createNode(parentNode: Node, buildContext: BuildContext) = lambdaError() From e89d21b1b2fa8599a8b3a3621786204ae72fb5b5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 14:41:00 +0200 Subject: [PATCH 074/145] Fix issue after rebase. --- .../viewfolder/impl/DefaultViewFolderEntryPointTest.kt | 8 ++++---- .../mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt b/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt index 752c1f93d0..47d5992d8c 100644 --- a/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt +++ b/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt @@ -12,7 +12,7 @@ import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.viewfolder.api.ViewFolderEntryPoint -import io.element.android.features.viewfolder.impl.root.ViewFolderRootNode +import io.element.android.features.viewfolder.impl.root.ViewFolderFlowNode import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import org.junit.Rule @@ -29,7 +29,7 @@ class DefaultViewFolderEntryPointTest { fun `test node builder`() { val entryPoint = DefaultViewFolderEntryPoint() val parentNode = TestParentNode.create { buildContext, plugins -> - ViewFolderRootNode( + ViewFolderFlowNode( buildContext = buildContext, plugins = plugins, ) @@ -44,8 +44,8 @@ class DefaultViewFolderEntryPointTest { .params(params) .callback(callback) .build() - assertThat(result).isInstanceOf(ViewFolderRootNode::class.java) - assertThat(result.plugins).contains(ViewFolderRootNode.Inputs(params.rootPath)) + assertThat(result).isInstanceOf(ViewFolderFlowNode::class.java) + assertThat(result.plugins).contains(ViewFolderFlowNode.Inputs(params.rootPath)) assertThat(result.plugins).contains(callback) } } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt index 27bf059199..0f8b0fedfb 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt @@ -15,7 +15,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint -import io.element.android.libraries.mediaviewer.impl.gallery.root.MediaGalleryRootNode +import io.element.android.libraries.mediaviewer.impl.gallery.root.MediaGalleryFlowNode import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import org.junit.Rule @@ -32,7 +32,7 @@ class DefaultMediaGalleryEntryPointTest { fun `test node builder`() { val entryPoint = DefaultMediaGalleryEntryPoint() val parentNode = TestParentNode.create { buildContext, plugins -> - MediaGalleryRootNode( + MediaGalleryFlowNode( buildContext = buildContext, plugins = plugins, mediaViewerEntryPoint = object : MediaViewerEntryPoint { @@ -47,7 +47,7 @@ class DefaultMediaGalleryEntryPointTest { val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) .callback(callback) .build() - assertThat(result).isInstanceOf(MediaGalleryRootNode::class.java) + assertThat(result).isInstanceOf(MediaGalleryFlowNode::class.java) assertThat(result.plugins).contains(callback) } } From c44bf89ed5fa27472c5bf4bb81eb4920ed0db6e8 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 16 Sep 2025 14:51:02 +0200 Subject: [PATCH 075/145] design (join room) : update design of join room screen --- .../features/joinroom/impl/JoinRoomState.kt | 1 - .../features/joinroom/impl/JoinRoomView.kt | 190 ++++++++++++------ .../joinroom/impl/JoinRoomPresenterTest.kt | 40 ++-- .../impl/RoomAliasResolverView.kt | 2 +- .../roomdetails/impl/RoomDetailsView.kt | 4 +- .../atoms/RoomPreviewDescriptionAtom.kt | 12 +- .../atomic/atoms/RoomPreviewSubtitleAtom.kt | 2 +- .../atomic/atoms/RoomPreviewTitleAtom.kt | 2 +- .../atomic/organisms/RoomPreviewOrganism.kt | 5 +- .../components/avatar/AvatarSize.kt | 4 +- .../matrix/ui/components/SpaceHeaderView.kt | 82 ++++---- .../DefaultNotificationConversationService.kt | 2 +- 12 files changed, 198 insertions(+), 148 deletions(-) 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 36a74c813e..6ecdcf4ba2 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 @@ -101,7 +101,6 @@ sealed interface ContentState { sealed interface JoinAuthorisationStatus { data object None : JoinAuthorisationStatus - data class IsSpace(val applicationName: String) : JoinAuthorisationStatus data class IsInvited(val inviteData: InviteData, val inviteSender: InviteSender?) : JoinAuthorisationStatus data class IsBanned(val banSender: InviteSender?, val reason: String?) : JoinAuthorisationStatus data object IsKnocked : JoinAuthorisationStatus diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 03598425e9..af4665e5da 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -7,21 +7,20 @@ package io.element.android.features.joinroom.impl +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api @@ -38,6 +37,7 @@ 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.features.invite.api.InviteData import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom import io.element.android.libraries.designsystem.atomic.atoms.RoomPreviewDescriptionAtom @@ -65,14 +65,21 @@ 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.CircularProgressIndicator +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.IconSource 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.TextField import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.designsystem.theme.placeholderBackground import io.element.android.libraries.matrix.api.core.RoomIdOrAlias -import io.element.android.libraries.matrix.ui.components.InviteSenderView +import io.element.android.libraries.matrix.api.room.join.JoinRule +import io.element.android.libraries.matrix.ui.components.SpaceInfoRow +import io.element.android.libraries.matrix.ui.components.SpaceMembersView +import io.element.android.libraries.matrix.ui.model.InviteSender import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.persistentListOf @Composable fun JoinRoomView( @@ -92,7 +99,7 @@ fun JoinRoomView( containerColor = Color.Transparent, contentPadding = PaddingValues( horizontal = 16.dp, - vertical = 32.dp + vertical = 24.dp ), topBar = { JoinRoomTopBar( @@ -220,12 +227,14 @@ private fun JoinRoomFooter( onClick = { onDeclineInvite(joinAuthorisationStatus.inviteData, false) }, modifier = Modifier.weight(1f), size = ButtonSize.LargeLowPadding, + leadingIcon = IconSource.Vector(CompoundIcons.Close()) ) Button( text = stringResource(CommonStrings.action_accept), onClick = { onAcceptInvite(joinAuthorisationStatus.inviteData) }, modifier = Modifier.weight(1f), size = ButtonSize.LargeLowPadding, + leadingIcon = IconSource.Vector(CompoundIcons.Check()) ) } Spacer(modifier = Modifier.height(24.dp)) @@ -278,7 +287,6 @@ private fun JoinRoomFooter( JoinAuthorisationStatus.Unknown -> JoinRestrictedFooter(onJoinRoom) JoinAuthorisationStatus.Restricted -> JoinRestrictedFooter(onJoinRoom) JoinAuthorisationStatus.Unauthorized -> JoinUnauthorizedFooter(onGoBack) - is JoinAuthorisationStatus.IsSpace -> UnsupportedSpaceFooter(joinAuthorisationStatus.applicationName, onGoBack) JoinAuthorisationStatus.None -> Unit } } @@ -397,19 +405,40 @@ private fun JoinRoomContent( IsKnockedLoadedContent() } else -> { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - val inviteSender = (contentState.joinAuthorisationStatus as? JoinAuthorisationStatus.IsInvited)?.inviteSender - if (inviteSender != null) { - InviteSenderView(inviteSender = inviteSender, hideAvatarImage = hideAvatarsImages) - Spacer(modifier = Modifier.height(32.dp)) - } + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.verticalScroll(rememberScrollState()) + ) { DefaultLoadedContent( - modifier = Modifier.verticalScroll(rememberScrollState()), contentState = contentState, - knockMessage = knockMessage, hideAvatarImage = hideAvatarsImages, - onKnockMessageUpdate = onKnockMessageUpdate ) + when (contentState.joinAuthorisationStatus) { + is JoinAuthorisationStatus.IsInvited -> { + val inviteSender = contentState.joinAuthorisationStatus.inviteSender + if (inviteSender != null) { + Spacer(Modifier.height(16.dp)) + InvitedByView(inviteSender, hideAvatarsImages) + } + } + is JoinAuthorisationStatus.CanKnock -> { + Spacer(modifier = Modifier.height(24.dp)) + val supportingText = if (knockMessage.isNotEmpty()) { + "${knockMessage.length}/$MAX_KNOCK_MESSAGE_LENGTH" + } else { + stringResource(R.string.screen_join_room_knock_message_description) + } + TextField( + value = knockMessage, + onValueChange = onKnockMessageUpdate, + maxLines = 3, + minLines = 3, + modifier = Modifier.fillMaxWidth(), + supportingText = supportingText + ) + } + else -> Unit + } } } } @@ -422,6 +451,45 @@ private fun JoinRoomContent( } } +@Composable +private fun InvitedByView( + sender: InviteSender, + hideAvatarImage: Boolean, + modifier: Modifier = Modifier +) { + Column( + modifier + .fillMaxWidth() + .padding(vertical = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "Invited by", + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary + ) + Spacer(Modifier.height(8.dp)) + Avatar( + avatarData = sender.avatarData, + avatarType = AvatarType.User, + hideImage = hideAvatarImage, + forcedAvatarSize = AvatarSize.RoomPreviewInviter.dp + ) + Spacer(Modifier.height(8.dp)) + Text( + text = sender.displayName, + style = ElementTheme.typography.fontBodyLgRegular, + color = ElementTheme.colors.textPrimary + ) + Spacer(Modifier.height(4.dp)) + Text( + text = sender.userId.value, + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textSecondary + ) + } +} + @Composable private fun UnknownRoomContent( modifier: Modifier = Modifier @@ -429,7 +497,21 @@ private fun UnknownRoomContent( RoomPreviewOrganism( modifier = modifier, avatar = { - Spacer(modifier = Modifier.size(AvatarSize.RoomHeader.dp)) + Box( + modifier = modifier + .size(AvatarSize.RoomPreviewHeader.dp) + .background( + color = ElementTheme.colors.placeholderBackground, + shape = CircleShape + ) + ) { + Icon( + modifier = Modifier.align(Alignment.Center), + tint = ElementTheme.colors.iconPrimary, + imageVector = CompoundIcons.VisibilityOff(), + contentDescription = null, + ) + } }, title = { RoomPreviewTitleAtom(stringResource(R.string.screen_join_room_title_no_preview)) @@ -448,7 +530,7 @@ private fun IncompleteContent( RoomPreviewOrganism( modifier = modifier, avatar = { - PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) + PlaceholderAtom(width = AvatarSize.RoomPreviewHeader.dp, height = AvatarSize.RoomPreviewHeader.dp) }, title = { when (roomIdOrAlias) { @@ -471,43 +553,32 @@ private fun IncompleteContent( @Composable private fun IsKnockedLoadedContent(modifier: Modifier = Modifier) { - BoxWithConstraints( - modifier = modifier - .fillMaxHeight() - .padding(horizontal = 16.dp), - contentAlignment = Alignment.Center, - ) { - IconTitleSubtitleMolecule( - modifier = Modifier.sizeIn(minHeight = maxHeight * 0.7f), - iconStyle = BigIcon.Style.SuccessSolid, - title = stringResource(R.string.screen_join_room_knock_sent_title), - subTitle = stringResource(R.string.screen_join_room_knock_sent_description), - ) - } + IconTitleSubtitleMolecule( + modifier = modifier.padding(horizontal = 8.dp), + iconStyle = BigIcon.Style.SuccessSolid, + title = stringResource(R.string.screen_join_room_knock_sent_title), + subTitle = stringResource(R.string.screen_join_room_knock_sent_description), + ) } @Composable private fun DefaultLoadedContent( contentState: ContentState.Loaded, - knockMessage: String, hideAvatarImage: Boolean, - onKnockMessageUpdate: (String) -> Unit, modifier: Modifier = Modifier, ) { RoomPreviewOrganism( modifier = modifier, avatar = { Avatar( - contentState.avatarData(AvatarSize.RoomHeader), + contentState.avatarData(AvatarSize.RoomPreviewHeader), hideImage = hideAvatarImage, - avatarType = AvatarType.Room(), + avatarType = if (contentState.isSpace) AvatarType.Space() else AvatarType.Room(), ) }, title = { if (contentState.name != null) { - RoomPreviewTitleAtom( - title = contentState.name, - ) + RoomPreviewTitleAtom(title = contentState.name) } else { RoomPreviewTitleAtom( title = stringResource(id = CommonStrings.common_no_room_name), @@ -516,37 +587,32 @@ private fun DefaultLoadedContent( } }, subtitle = { - if (contentState.alias != null) { - RoomPreviewSubtitleAtom(contentState.alias.value) - } - }, - description = { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - RoomPreviewDescriptionAtom(contentState.topic ?: "") - if (contentState.joinAuthorisationStatus is JoinAuthorisationStatus.CanKnock) { - Spacer(modifier = Modifier.height(24.dp)) - val supportingText = if (knockMessage.isNotEmpty()) { - "${knockMessage.length}/$MAX_KNOCK_MESSAGE_LENGTH" - } else { - stringResource(R.string.screen_join_room_knock_message_description) - } - TextField( - value = knockMessage, - onValueChange = onKnockMessageUpdate, - maxLines = 3, - minLines = 3, - modifier = Modifier.fillMaxWidth(), - supportingText = supportingText + when { + contentState.isSpace -> { + SpaceInfoRow( + joinRule = contentState.joinRule ?: JoinRule.Public, + numberOfRooms = contentState.childrenCount ?: 0, ) } + contentState.alias != null -> { + RoomPreviewSubtitleAtom(contentState.alias.value) + } } }, + description = { + RoomPreviewDescriptionAtom( + contentState.topic ?: "", + maxLines = if (contentState.joinAuthorisationStatus is JoinAuthorisationStatus.CanJoin) Int.MAX_VALUE else 2 + ) + }, memberCount = { if (contentState.showMemberCount) { - MembersCountMolecule(memberCount = contentState.numberOfMembers?.toInt() ?: 0) + val membersCount = contentState.numberOfMembers?.toInt() ?: 0 + if (contentState.isSpace) { + SpaceMembersView(persistentListOf(), membersCount) + } else { + MembersCountMolecule(memberCount = membersCount) + } } } ) 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 5a6631146d..6deb39fba4 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 @@ -655,7 +655,10 @@ class JoinRoomPresenterTest { isDm = false, roomType = RoomType.Room, roomAvatarUrl = "avatarUrl", - joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin + joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin, + joinRule = JoinRule.Public, + childrenCount = null, + heroes = persistentListOf() ) ) } @@ -724,7 +727,10 @@ class JoinRoomPresenterTest { ), membershipChangeReason = null, ), - ) + ), + joinRule = JoinRule.Public, + childrenCount = null, + heroes = persistentListOf() ) ) } @@ -789,7 +795,10 @@ class JoinRoomPresenterTest { membershipChangeReason = null, ), reason = null, - ) + ), + joinRule = JoinRule.Public, + childrenCount = null, + heroes = persistentListOf() ) ) } @@ -842,7 +851,10 @@ class JoinRoomPresenterTest { isDm = false, roomType = RoomType.Room, roomAvatarUrl = "avatarUrl", - joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked + joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked, + joinRule = JoinRule.Public, + childrenCount = null, + heroes = persistentListOf() ) ) } @@ -949,26 +961,6 @@ class JoinRoomPresenterTest { } } - @Test - fun `present - when room is not known RoomPreview is loaded as Space`() = runTest { - val client = FakeMatrixClient( - getNotJoinedRoomResult = { _, _ -> - Result.success( - aRoomPreview(info = aRoomPreviewInfo(isSpace = true)) - ) - } - ) - val presenter = createJoinRoomPresenter( - matrixClient = client - ) - presenter.test { - skipItems(1) - awaitItem().also { state -> - assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.UnsupportedSpace("AppName")) - } - } - } - @Test fun `present - when room is not known RoomPreview is loaded with error`() = runTest { val client = FakeMatrixClient( diff --git a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverView.kt b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverView.kt index ef2cc47ecc..9d7536b2f5 100644 --- a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverView.kt +++ b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverView.kt @@ -117,7 +117,7 @@ private fun RoomAliasResolverContent( RoomPreviewOrganism( modifier = modifier, avatar = { - PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) + PlaceholderAtom(width = AvatarSize.RoomPreviewHeader.dp, height = AvatarSize.RoomPreviewHeader.dp) }, title = { RoomPreviewSubtitleAtom(roomAlias.value) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 3fdb2a0800..61d5ba115a 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -396,10 +396,10 @@ private fun RoomHeaderSection( horizontalAlignment = Alignment.CenterHorizontally, ) { Avatar( - avatarData = AvatarData(roomId.value, roomName, avatarUrl, AvatarSize.RoomHeader), + avatarData = AvatarData(roomId.value, roomName, avatarUrl, AvatarSize.RoomDetailsHeader), avatarType = AvatarType.Room( heroes = heroes.map { user -> - user.getAvatarData(size = AvatarSize.RoomHeader) + user.getAvatarData(size = AvatarSize.RoomDetailsHeader) }.toPersistentList(), isTombstoned = isTombstoned, ), diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewDescriptionAtom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewDescriptionAtom.kt index 8ca1a01e6b..3aece9889e 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewDescriptionAtom.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewDescriptionAtom.kt @@ -15,14 +15,18 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.libraries.designsystem.theme.components.Text @Composable -fun RoomPreviewDescriptionAtom(description: String, modifier: Modifier = Modifier) { +fun RoomPreviewDescriptionAtom( + description: String, + modifier: Modifier = Modifier, + maxLines: Int = Int.MAX_VALUE, +) { Text( modifier = modifier, text = description, - style = ElementTheme.typography.fontBodySmRegular, + style = ElementTheme.typography.fontBodyMdRegular, textAlign = TextAlign.Center, - color = ElementTheme.colors.textSecondary, - maxLines = 3, + color = ElementTheme.colors.textPrimary, + maxLines = maxLines, overflow = TextOverflow.Ellipsis, ) } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewSubtitleAtom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewSubtitleAtom.kt index ae705e6bfb..4fe52f5443 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewSubtitleAtom.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewSubtitleAtom.kt @@ -18,7 +18,7 @@ fun RoomPreviewSubtitleAtom(subtitle: String, modifier: Modifier = Modifier) { Text( modifier = modifier, text = subtitle, - style = ElementTheme.typography.fontBodyMdRegular, + style = ElementTheme.typography.fontBodyLgRegular, textAlign = TextAlign.Center, color = ElementTheme.colors.textSecondary, ) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewTitleAtom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewTitleAtom.kt index 2ede537931..2c77dc8461 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewTitleAtom.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoomPreviewTitleAtom.kt @@ -23,7 +23,7 @@ fun RoomPreviewTitleAtom( Text( modifier = modifier, text = title, - style = ElementTheme.typography.fontHeadingMdBold, + style = ElementTheme.typography.fontHeadingLgBold, textAlign = TextAlign.Center, fontStyle = fontStyle, color = ElementTheme.colors.textPrimary, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/RoomPreviewOrganism.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/RoomPreviewOrganism.kt index 511eb298ea..dac9f00a7c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/RoomPreviewOrganism.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/RoomPreviewOrganism.kt @@ -34,14 +34,13 @@ fun RoomPreviewOrganism( title() Spacer(modifier = Modifier.height(8.dp)) subtitle() - Spacer(modifier = Modifier.height(8.dp)) if (memberCount != null) { + Spacer(modifier = Modifier.height(8.dp)) memberCount() } - Spacer(modifier = Modifier.height(8.dp)) if (description != null) { + Spacer(modifier = Modifier.height(16.dp)) description() } - Spacer(modifier = Modifier.height(24.dp)) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt index 9e9ebb6181..b7d6339d02 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt @@ -14,7 +14,7 @@ enum class AvatarSize(val dp: Dp) { CurrentUserTopBar(32.dp), IncomingCall(140.dp), - RoomHeader(96.dp), + RoomDetailsHeader(96.dp), RoomListItem(52.dp), SpaceListItem(52.dp), @@ -68,5 +68,7 @@ enum class AvatarSize(val dp: Dp) { OrganizationHeader(64.dp), SpaceHeader(64.dp), + RoomPreviewHeader(64.dp), + RoomPreviewInviter(56.dp), SpaceMember(24.dp), } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt index 11e9f37c8b..ecfde229c9 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt @@ -7,19 +7,14 @@ package io.element.android.libraries.matrix.ui.components -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.datasource.LoremIpsum import androidx.compose.ui.unit.dp -import io.element.android.compound.theme.ElementTheme +import io.element.android.libraries.designsystem.atomic.atoms.RoomPreviewDescriptionAtom +import io.element.android.libraries.designsystem.atomic.atoms.RoomPreviewTitleAtom +import io.element.android.libraries.designsystem.atomic.organisms.RoomPreviewOrganism import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -47,47 +42,40 @@ fun SpaceHeaderView( modifier: Modifier = Modifier, topicMaxLines: Int = Int.MAX_VALUE, ) { - Column( - modifier = modifier - .fillMaxWidth() - .padding(top = 32.dp, bottom = 24.dp, start = 16.dp, end = 16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - Avatar( - avatarData = avatarData, - avatarType = AvatarType.Space(false), - ) - name?.let { - Text( - text = name, - style = ElementTheme.typography.fontHeadingLgBold, - color = ElementTheme.colors.textPrimary, - textAlign = TextAlign.Center, + RoomPreviewOrganism( + modifier = modifier.padding(24.dp), + avatar = { + Avatar( + avatarData = avatarData, + avatarType = AvatarType.Space(), ) - } - if (joinRule != null) { - SpaceInfoRow( - joinRule = joinRule, - numberOfRooms = numberOfRooms, + }, + title = { + name?.let { + RoomPreviewTitleAtom(title = name) + } + }, + subtitle = { + if (joinRule != null) { + SpaceInfoRow( + joinRule = joinRule, + numberOfRooms = numberOfRooms, + ) + } + }, + description = if (topic != null) { + { RoomPreviewDescriptionAtom(description = topic, maxLines = topicMaxLines) } + } else { + null + }, + memberCount = { + SpaceMembersView( + heroes = heroes, + numberOfMembers = numberOfMembers, + modifier = Modifier.padding(horizontal = 32.dp), ) - } - SpaceMembersView( - heroes = heroes, - numberOfMembers = numberOfMembers, - modifier = Modifier.padding(horizontal = 32.dp), - ) - topic?.let { - Text( - text = topic, - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textPrimary, - textAlign = TextAlign.Center, - maxLines = topicMaxLines, - overflow = TextOverflow.Ellipsis, - ) - } - } + }, + ) } @PreviewsDayNight diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/conversations/DefaultNotificationConversationService.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/conversations/DefaultNotificationConversationService.kt index 24b69a2e58..bda5a593d5 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/conversations/DefaultNotificationConversationService.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/conversations/DefaultNotificationConversationService.kt @@ -105,7 +105,7 @@ class DefaultNotificationConversationService( targetSize = defaultShortcutIconSize.toLong() )?.let(IconCompat::createWithBitmap) ?: InitialsAvatarBitmapGenerator(useDarkTheme = useDarkTheme) - .generateBitmap(defaultShortcutIconSize, AvatarData(id = roomId.value, name = roomName, size = AvatarSize.RoomHeader)) + .generateBitmap(defaultShortcutIconSize, AvatarData(id = roomId.value, name = roomName, size = AvatarSize.RoomDetailsHeader)) ?.let(IconCompat::createWithAdaptiveBitmap) val shortcutInfo = ShortcutInfoCompat.Builder(context, createShortcutId(sessionId, roomId)) From 2d9e9d13268c00b17270be217fdea2aff2608191 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 15:50:57 +0200 Subject: [PATCH 076/145] Add unit test on ChangeRoomMemberRolesListType.toRoomMemberRole() --- .../impl/ChangeRolesNode.kt | 2 +- .../impl/ChangeRolesNodeTest.kt | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNodeTest.kt diff --git a/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNode.kt b/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNode.kt index 26b1af6bbb..697297372f 100644 --- a/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNode.kt +++ b/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNode.kt @@ -55,7 +55,7 @@ class ChangeRolesNode( } } -private fun ChangeRoomMemberRolesListType.toRoomMemberRole() = when (this) { +internal fun ChangeRoomMemberRolesListType.toRoomMemberRole() = when (this) { ChangeRoomMemberRolesListType.Admins -> RoomMember.Role.Admin ChangeRoomMemberRolesListType.Moderators -> RoomMember.Role.Moderator ChangeRoomMemberRolesListType.SelectNewOwnersWhenLeaving -> RoomMember.Role.Owner(isCreator = false) diff --git a/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNodeTest.kt b/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNodeTest.kt new file mode 100644 index 0000000000..5a47f52e89 --- /dev/null +++ b/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesNodeTest.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.changeroommemberroles.impl + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.changeroommemberroes.api.ChangeRoomMemberRolesListType +import io.element.android.libraries.matrix.api.room.RoomMember +import org.junit.Test + +class ChangeRolesNodeTest { + @Test + fun `test toRoomMemberRole`() { + assertThat(ChangeRoomMemberRolesListType.Admins.toRoomMemberRole()) + .isEqualTo(RoomMember.Role.Admin) + assertThat(ChangeRoomMemberRolesListType.Moderators.toRoomMemberRole()) + .isEqualTo(RoomMember.Role.Moderator) + assertThat(ChangeRoomMemberRolesListType.SelectNewOwnersWhenLeaving.toRoomMemberRole()) + .isEqualTo(RoomMember.Role.Owner(false)) + } +} From 2f4ab0d1e0824492c0d6697a21a694c8d3b7b237 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Sep 2025 15:54:10 +0200 Subject: [PATCH 077/145] Add .idea/copilot.* to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e3fcb2ef13..e1b1c5c8ab 100644 --- a/.gitignore +++ b/.gitignore @@ -62,6 +62,7 @@ captures/ # Android Studio 3 in .gitignore file. .idea/caches .idea/copilot +.idea/copilot.* .idea/inspectionProfiles # Shelved changes in the IDE .idea/shelf From cbad0c31d8fe3c2f097d7d3e3d9a4c77aabd8429 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 17 Sep 2025 12:18:37 +0200 Subject: [PATCH 078/145] Complete test on MediaGalleryPresenter --- .../impl/gallery/MediaGalleryPresenterTest.kt | 114 +++++++++++++++++- 1 file changed, 108 insertions(+), 6 deletions(-) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt index 80005facd4..f126dab2b5 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt @@ -10,7 +10,9 @@ package io.element.android.libraries.mediaviewer.impl.gallery import android.net.Uri import app.cash.turbine.ReceiveTurbine import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.timeline.Timeline @@ -29,6 +31,7 @@ import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetSta import io.element.android.libraries.mediaviewer.impl.model.aMediaItemImage import io.element.android.libraries.mediaviewer.test.FakeLocalMediaActions import io.element.android.libraries.mediaviewer.test.FakeLocalMediaFactory +import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -147,8 +150,8 @@ class MediaGalleryPresenterTest { val presenter = createMediaGalleryPresenter( room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo(name = A_ROOM_NAME), + sessionId = A_USER_ID, + initialRoomInfo = aRoomInfo(name = A_ROOM_NAME), canRedactOtherResult = { Result.success(canDeleteOther) }, ), createTimelineResult = { Result.success(FakeTimeline()) } @@ -223,23 +226,122 @@ class MediaGalleryPresenterTest { } @Test - fun `present - share item`() = runTest { + fun `present - share item - item not found`() = runTest { val presenter = createMediaGalleryPresenter() presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MediaGalleryEvents.Share(AN_EVENT_ID)) } - // TODO Add more test on this part } @Test - fun `present - save on disk`() = runTest { + fun `present - share item - item found`() = runTest { + val mediaGalleryDataSource = FakeMediaGalleryDataSource( + startLambda = { }, + ) + mediaGalleryDataSource.emitGroupedMediaItems( + AsyncData.Success( + aGroupedMediaItems( + imageAndVideoItems = listOf(aMediaItemImage(eventId = AN_EVENT_ID)), + fileItems = emptyList(), + ) + ) + ) + val presenter = createMediaGalleryPresenter( + mediaGalleryDataSource = mediaGalleryDataSource, + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.eventSink(MediaGalleryEvents.Share(AN_EVENT_ID)) + val finalState = awaitItem() + assertThat(finalState.snackbarMessage).isNull() + } + } + + @Test + fun `present - share item - item found - download error`() = runTest { + val mediaGalleryDataSource = FakeMediaGalleryDataSource( + startLambda = { }, + ) + mediaGalleryDataSource.emitGroupedMediaItems( + AsyncData.Success( + aGroupedMediaItems( + imageAndVideoItems = listOf(aMediaItemImage(eventId = AN_EVENT_ID)), + fileItems = emptyList(), + ) + ) + ) + val presenter = createMediaGalleryPresenter( + mediaGalleryDataSource = mediaGalleryDataSource, + matrixMediaLoader = FakeMatrixMediaLoader().apply { shouldFail = true }, + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.eventSink(MediaGalleryEvents.Share(AN_EVENT_ID)) + skipItems(1) + val finalState = awaitItem() + assertThat(finalState.snackbarMessage).isInstanceOf(SnackbarMessage::class.java) + } + } + + @Test + fun `present - save on disk - item not found`() = runTest { val presenter = createMediaGalleryPresenter() presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MediaGalleryEvents.SaveOnDisk(AN_EVENT_ID)) } - // TODO Add more test on this part + } + + @Test + fun `present - save on disk - item found`() = runTest { + val mediaGalleryDataSource = FakeMediaGalleryDataSource( + startLambda = { }, + ) + mediaGalleryDataSource.emitGroupedMediaItems( + AsyncData.Success( + aGroupedMediaItems( + imageAndVideoItems = listOf(aMediaItemImage(eventId = AN_EVENT_ID)), + fileItems = emptyList(), + ) + ) + ) + val presenter = createMediaGalleryPresenter( + mediaGalleryDataSource = mediaGalleryDataSource, + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.eventSink(MediaGalleryEvents.SaveOnDisk(AN_EVENT_ID)) + skipItems(1) + val finalState = awaitItem() + assertThat(finalState.snackbarMessage?.messageResId).isEqualTo(CommonStrings.common_file_saved_on_disk_android) + } + } + + @Test + fun `present - save on disk - item found - download error`() = runTest { + val mediaGalleryDataSource = FakeMediaGalleryDataSource( + startLambda = { }, + ) + mediaGalleryDataSource.emitGroupedMediaItems( + AsyncData.Success( + aGroupedMediaItems( + imageAndVideoItems = listOf(aMediaItemImage(eventId = AN_EVENT_ID)), + fileItems = emptyList(), + ) + ) + ) + val presenter = createMediaGalleryPresenter( + mediaGalleryDataSource = mediaGalleryDataSource, + matrixMediaLoader = FakeMatrixMediaLoader().apply { shouldFail = true }, + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.eventSink(MediaGalleryEvents.SaveOnDisk(AN_EVENT_ID)) + skipItems(1) + val finalState = awaitItem() + assertThat(finalState.snackbarMessage).isInstanceOf(SnackbarMessage::class.java) + } } @Test From 508aef98ff6a406fc0cdfea55876cf7701936fca Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 16 Sep 2025 09:00:17 +0200 Subject: [PATCH 079/145] Use the new RtcNotification instead of deprecated CallNotify --- .../call/api/ElementCallEntryPoint.kt | 2 ++ .../call/impl/DefaultElementCallEntryPoint.kt | 2 ++ .../notifications/CallNotificationData.kt | 1 + .../RingingCallNotificationCreator.kt | 2 ++ .../call/impl/ui/IncomingCallScreen.kt | 1 + .../call/impl/utils/ActiveCallManager.kt | 21 +++++++++++++++---- .../impl/actionlist/ActionListPresenter.kt | 4 ++-- .../impl/actionlist/ActionListView.kt | 4 ++-- .../components/TimelineItemCallNotifyView.kt | 4 ++-- .../timeline/components/TimelineItemRow.kt | 4 ++-- .../event/TimelineItemEventContentView.kt | 4 ++-- .../event/TimelineItemContentFactory.kt | 4 ++-- .../impl/timeline/groups/Groupability.kt | 4 ++-- .../model/event/TimelineItemEventContent.kt | 2 +- ... => TimelineItemRtcNotificationContent.kt} | 4 ++-- .../impl/timeline/protection/TimelineItem.kt | 4 ++-- .../DefaultMessageSummaryFormatter.kt | 4 ++-- .../api/notification/NotificationData.kt | 1 + .../api/timeline/item/event/EventType.kt | 3 ++- ...imelineEventToNotificationContentMapper.kt | 14 ++++++++----- .../matrix/impl/room/MessageEventType.kt | 4 ++-- .../matrix/impl/timeline/RustTimeline.kt | 1 + .../item/event/TimelineEventContentMapper.kt | 2 +- .../CallNotificationEventResolver.kt | 3 ++- .../factories/NotificationCreator.kt | 6 +++--- .../model/NotifiableRingingCallEvent.kt | 1 + .../push/impl/push/DefaultPushHandler.kt | 1 + 27 files changed, 69 insertions(+), 38 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/{TimelineItemCallNotifyContent.kt => TimelineItemRtcNotificationContent.kt} (65%) diff --git a/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt b/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt index 53e1b8c846..8de7a3839b 100644 --- a/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt +++ b/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt @@ -29,6 +29,7 @@ interface ElementCallEntryPoint { * @param senderName The name of the sender of the event that started the call. * @param avatarUrl The avatar url of the room or DM. * @param timestamp The timestamp of the event that started the call. + * @param expirationTimestamp The timestamp at which the call should stop ringing. * @param notificationChannelId The id of the notification channel to use for the call notification. * @param textContent The text content of the notification. If null the default content from the system will be used. */ @@ -40,6 +41,7 @@ interface ElementCallEntryPoint { senderName: String?, avatarUrl: String?, timestamp: Long, + expirationTimestamp: Long, notificationChannelId: String, textContent: String?, ) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/DefaultElementCallEntryPoint.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/DefaultElementCallEntryPoint.kt index 3b937dbf92..a1c07462f8 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/DefaultElementCallEntryPoint.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/DefaultElementCallEntryPoint.kt @@ -43,6 +43,7 @@ class DefaultElementCallEntryPoint( senderName: String?, avatarUrl: String?, timestamp: Long, + expirationTimestamp: Long, notificationChannelId: String, textContent: String?, ) { @@ -55,6 +56,7 @@ class DefaultElementCallEntryPoint( senderName = senderName, avatarUrl = avatarUrl, timestamp = timestamp, + expirationTimestamp = expirationTimestamp, notificationChannelId = notificationChannelId, textContent = textContent, ) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt index 7c97cc8529..8ebb8b8080 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt @@ -26,4 +26,5 @@ data class CallNotificationData( val notificationChannelId: String, val timestamp: Long, val textContent: String?, + val expirationTimestamp: Long, ) : Parcelable diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt index 988105ae06..2f8ce3e53a 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt @@ -64,6 +64,7 @@ class RingingCallNotificationCreator( roomAvatarUrl: String?, notificationChannelId: String, timestamp: Long, + expirationTimestamp: Long, textContent: String?, ): Notification? { val matrixClient = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return null @@ -88,6 +89,7 @@ class RingingCallNotificationCreator( notificationChannelId = notificationChannelId, timestamp = timestamp, textContent = textContent, + expirationTimestamp = expirationTimestamp, ) val declineIntent = PendingIntentCompat.getBroadcast( diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallScreen.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallScreen.kt index 954fa3568f..9483b91a14 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallScreen.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallScreen.kt @@ -176,6 +176,7 @@ internal fun IncomingCallScreenPreview() = ElementPreview { notificationChannelId = "incoming_call", timestamp = 0L, textContent = null, + expirationTimestamp = 1000L, ), onAnswer = {}, onCancel = {}, diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index 0895e6860b..b609bfcbce 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -53,7 +53,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import timber.log.Timber -import kotlin.time.Duration.Companion.seconds +import kotlin.math.min /** * Manages the active call state. @@ -118,8 +118,20 @@ class DefaultActiveCallManager( override suspend fun registerIncomingCall(notificationData: CallNotificationData) { mutex.withLock { + val ringDuration = + min( + notificationData.expirationTimestamp - System.currentTimeMillis(), + ElementCallConfig.RINGING_CALL_DURATION_SECONDS * 1000L + ) + + if (ringDuration < 0) { + // Should already have stopped ringing, ignore. + Timber.tag(tag).d("Received timed-out incoming ringing call for room id: ${notificationData.roomId}, cancel ringing") + return + } + appForegroundStateService.updateHasRingingCall(true) - Timber.tag(tag).d("Received incoming call for room id: ${notificationData.roomId}") + Timber.tag(tag).d("Received incoming call for room id: ${notificationData.roomId}, ringDuration: $ringDuration") if (activeCall.value != null) { displayMissedCallNotification(notificationData) Timber.tag(tag).w("Already have an active call, ignoring incoming call: $notificationData") @@ -138,14 +150,14 @@ class DefaultActiveCallManager( showIncomingCallNotification(notificationData) // Wait for the ringing call to time out - delay(ElementCallConfig.RINGING_CALL_DURATION_SECONDS.seconds) + delay(timeMillis = ringDuration) incomingCallTimedOut(displayMissedCallNotification = true) } // Acquire a wake lock to keep the device awake during the incoming call, so we can process the room info data if (activeWakeLock?.isHeld == false) { Timber.tag(tag).d("Acquiring partial wakelock") - activeWakeLock.acquire(ElementCallConfig.RINGING_CALL_DURATION_SECONDS * 1000L) + activeWakeLock.acquire(ringDuration) } } } @@ -236,6 +248,7 @@ class DefaultActiveCallManager( notificationChannelId = notificationData.notificationChannelId, timestamp = notificationData.timestamp, textContent = notificationData.textContent, + expirationTimestamp = notificationData.expirationTimestamp, ) ?: return runCatchingExceptions { notificationManagerCompat.notify( 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 6263576c53..a0b8db9979 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 @@ -25,12 +25,12 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory 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.TimelineItemEventContentWithAttachment 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.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent import io.element.android.features.messages.impl.timeline.model.event.canBeCopied import io.element.android.features.messages.impl.timeline.model.event.canBeForwarded @@ -242,7 +242,7 @@ class DefaultActionListPresenter( private fun Iterable.postFilter(content: TimelineItemEventContent): Iterable { return filter { action -> when (content) { - is TimelineItemCallNotifyContent, + is TimelineItemRtcNotificationContent, is TimelineItemLegacyCallInviteContent, is TimelineItemStateContent -> action == TimelineItemAction.ViewSource is TimelineItemRedactedContent -> { 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 78b4b43112..bb57cc82d4 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 @@ -56,7 +56,6 @@ import io.element.android.features.messages.impl.timeline.a11y.a11yReactionActio 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 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent @@ -64,6 +63,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent 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.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent @@ -306,7 +306,7 @@ private fun MessageSummary( is TimelineItemLegacyCallInviteContent -> { content = { ContentForBody(textContent) } } - is TimelineItemCallNotifyContent -> { + is TimelineItemRtcNotificationContent -> { content = { ContentForBody(stringResource(CommonStrings.common_call_started)) } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index 6cbd22c3fa..aaebfb4957 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -29,7 +29,7 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons 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.TimelineItemCallNotifyContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomcall.api.RoomCallStateProvider import io.element.android.libraries.designsystem.components.avatar.Avatar @@ -119,7 +119,7 @@ internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { .filter { it !is RoomCallState.Unavailable } .forEach { roomCallState -> TimelineItemCallNotifyView( - event = aTimelineItemEvent(content = TimelineItemCallNotifyContent()), + event = aTimelineItemEvent(content = TimelineItemRtcNotificationContent()), roomCallState = roomCallState, onLongClick = {}, onJoinCallClick = {}, 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 11d7b91e1e..119a235cf8 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 @@ -30,9 +30,9 @@ import io.element.android.features.messages.impl.timeline.TimelineRoomInfo import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData 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.TimelineItemLegacyCallInviteContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent 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.protection.TimelineProtectionEvent @@ -123,7 +123,7 @@ internal fun TimelineItemRow( eventSink = eventSink, ) } - is TimelineItemCallNotifyContent -> { + is TimelineItemRtcNotificationContent -> { TimelineItemCallNotifyView( modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 16.dp), event = timelineItem, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt index 332f58777c..8660d82e7c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt @@ -14,7 +14,6 @@ import io.element.android.features.messages.impl.timeline.components.layout.Cont import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.rememberPresenter import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent @@ -23,6 +22,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent 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.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent @@ -133,6 +133,6 @@ fun TimelineItemEventContentView( modifier = modifier ) } - is TimelineItemCallNotifyContent -> error("This shouldn't be rendered as the content of a bubble") + is TimelineItemRtcNotificationContent -> error("This shouldn't be rendered as the content of a bubble") } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt index 499c5349ae..643d0f55ad 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt @@ -8,9 +8,9 @@ package io.element.android.features.messages.impl.timeline.factories.event import dev.zacsweers.metro.Inject -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.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem @@ -61,7 +61,7 @@ class TimelineItemContentFactory( is StickerContent -> stickerFactory.create(itemContent) is PollContent -> pollFactory.create(eventTimelineItem, itemContent) is UnableToDecryptContent -> utdFactory.create(itemContent) - is CallNotifyContent -> TimelineItemCallNotifyContent() + is CallNotifyContent -> TimelineItemRtcNotificationContent() is UnknownContent -> TimelineItemUnknownContent } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt index 67a4d3da0d..a56a4d09e9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt @@ -9,7 +9,6 @@ package io.element.android.features.messages.impl.timeline.groups 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 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent @@ -19,6 +18,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemProfileChangeContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRoomMembershipContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent @@ -60,7 +60,7 @@ internal fun TimelineItem.Event.canBeGrouped(): Boolean { TimelineItemRedactedContent, TimelineItemUnknownContent, is TimelineItemLegacyCallInviteContent, - is TimelineItemCallNotifyContent -> false + is TimelineItemRtcNotificationContent -> false is TimelineItemProfileChangeContent, is TimelineItemRoomMembershipContent, is TimelineItemStateEventContent -> true 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 d011865964..be7c47439a 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 @@ -81,7 +81,7 @@ fun TimelineItemEventContent.canReact(): Boolean = is TimelineItemStateContent, is TimelineItemRedactedContent, is TimelineItemLegacyCallInviteContent, - is TimelineItemCallNotifyContent, + is TimelineItemRtcNotificationContent, TimelineItemUnknownContent -> false } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemCallNotifyContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt similarity index 65% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemCallNotifyContent.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt index 75d070d025..0c2f21fc5b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemCallNotifyContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt @@ -7,6 +7,6 @@ package io.element.android.features.messages.impl.timeline.model.event -class TimelineItemCallNotifyContent : TimelineItemEventContent { - override val type: String = "m.call.notify" +class TimelineItemRtcNotificationContent : TimelineItemEventContent { + override val type: String = "org.matrix.msc4075.rtc.notification" } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineItem.kt index 279a542081..1f306c74ea 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineItem.kt @@ -9,7 +9,6 @@ package io.element.android.features.messages.impl.timeline.protection 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 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEmoteContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent @@ -21,6 +20,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemProfileChangeContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRoomMembershipContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent @@ -38,7 +38,7 @@ fun TimelineItem.mustBeProtected(): Boolean { is TimelineItemVideoContent, is TimelineItemStickerContent -> true is TimelineItemAudioContent, - is TimelineItemCallNotifyContent, + is TimelineItemRtcNotificationContent, is TimelineItemEncryptedContent, is TimelineItemFileContent, TimelineItemLegacyCallInviteContent, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt index aacdfeb0e8..22c67ed2f2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt @@ -12,7 +12,6 @@ import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Inject 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 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent @@ -21,6 +20,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemProfileChangeContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent @@ -54,7 +54,7 @@ class DefaultMessageSummaryFormatter( is TimelineItemFileContent -> context.getString(CommonStrings.common_file) is TimelineItemAudioContent -> context.getString(CommonStrings.common_audio) is TimelineItemLegacyCallInviteContent -> context.getString(CommonStrings.common_unsupported_call) - is TimelineItemCallNotifyContent -> context.getString(CommonStrings.common_call_started) + is TimelineItemRtcNotificationContent -> context.getString(CommonStrings.common_call_started) } // Truncate the message to a safe length to avoid crashes in Compose .toSafeLength() 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 338193ed44..61195b68cc 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 @@ -52,6 +52,7 @@ sealed interface NotificationContent { data class CallNotify( val senderId: UserId, val type: CallNotifyType, + val expirationTimestampMillis: Long ) : MessageLike data object CallHangup : MessageLike diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventType.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventType.kt index 41d0dc7483..d6b354376c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventType.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventType.kt @@ -15,5 +15,6 @@ object EventType { // Call Events const val CALL_INVITE = "m.call.invite" - const val CALL_NOTIFY = "m.call.notify" + + const val RTC_NOTIFICATION = "org.matrix.msc4075.rtc.notification" } 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 85f87b271f..98cf2f7fc9 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 @@ -15,7 +15,7 @@ import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper import io.element.android.libraries.matrix.impl.timeline.item.event.EventMessageMapper import org.matrix.rustcomponents.sdk.MessageLikeEventContent -import org.matrix.rustcomponents.sdk.NotifyType +import org.matrix.rustcomponents.sdk.RtcNotificationType import org.matrix.rustcomponents.sdk.StateEventContent import org.matrix.rustcomponents.sdk.TimelineEvent import org.matrix.rustcomponents.sdk.TimelineEventType @@ -78,7 +78,11 @@ private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationCon MessageLikeEventContent.CallCandidates -> NotificationContent.MessageLike.CallCandidates MessageLikeEventContent.CallHangup -> NotificationContent.MessageLike.CallHangup MessageLikeEventContent.CallInvite -> NotificationContent.MessageLike.CallInvite(senderId) - is MessageLikeEventContent.CallNotify -> NotificationContent.MessageLike.CallNotify(senderId, notifyType.map()) + is MessageLikeEventContent.RtcNotification -> NotificationContent.MessageLike.CallNotify( + senderId = senderId, + type = notificationType.map(), + expirationTimestampMillis = expirationTs.toLong() + ) MessageLikeEventContent.KeyVerificationAccept -> NotificationContent.MessageLike.KeyVerificationAccept MessageLikeEventContent.KeyVerificationCancel -> NotificationContent.MessageLike.KeyVerificationCancel MessageLikeEventContent.KeyVerificationDone -> NotificationContent.MessageLike.KeyVerificationDone @@ -101,7 +105,7 @@ private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationCon } } -private fun NotifyType.map(): CallNotifyType = when (this) { - NotifyType.NOTIFY -> CallNotifyType.NOTIFY - NotifyType.RING -> CallNotifyType.RING +private fun RtcNotificationType.map(): CallNotifyType = when (this) { + RtcNotificationType.NOTIFY -> CallNotifyType.NOTIFY + RtcNotificationType.RING -> CallNotifyType.RING } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt index 0f7faf0317..6c42152d83 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt @@ -15,7 +15,7 @@ fun MessageEventType.map(): MessageLikeEventType = when (this) { MessageEventType.CALL_INVITE -> MessageLikeEventType.CALL_INVITE MessageEventType.CALL_HANGUP -> MessageLikeEventType.CALL_HANGUP MessageEventType.CALL_CANDIDATES -> MessageLikeEventType.CALL_CANDIDATES - MessageEventType.CALL_NOTIFY -> MessageLikeEventType.CALL_NOTIFY + MessageEventType.CALL_NOTIFY -> MessageLikeEventType.RTC_NOTIFICATION MessageEventType.KEY_VERIFICATION_READY -> MessageLikeEventType.KEY_VERIFICATION_READY MessageEventType.KEY_VERIFICATION_START -> MessageLikeEventType.KEY_VERIFICATION_START MessageEventType.KEY_VERIFICATION_CANCEL -> MessageLikeEventType.KEY_VERIFICATION_CANCEL @@ -41,7 +41,7 @@ fun MessageLikeEventType.map(): MessageEventType = when (this) { MessageLikeEventType.CALL_INVITE -> MessageEventType.CALL_INVITE MessageLikeEventType.CALL_HANGUP -> MessageEventType.CALL_HANGUP MessageLikeEventType.CALL_CANDIDATES -> MessageEventType.CALL_CANDIDATES - MessageLikeEventType.CALL_NOTIFY -> MessageEventType.CALL_NOTIFY + MessageLikeEventType.RTC_NOTIFICATION -> MessageEventType.CALL_NOTIFY MessageLikeEventType.KEY_VERIFICATION_READY -> MessageEventType.KEY_VERIFICATION_READY MessageLikeEventType.KEY_VERIFICATION_START -> MessageEventType.KEY_VERIFICATION_START MessageLikeEventType.KEY_VERIFICATION_CANCEL -> MessageEventType.KEY_VERIFICATION_CANCEL 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 b4888dafe0..9e1ade63a6 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 @@ -437,6 +437,7 @@ class RustTimeline( key = emoji, itemId = eventOrTransactionId.toRustEventOrTransactionId(), ) + return@runCatchingExceptions Unit } } 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 eeb063b28a..4bf4592c38 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 @@ -149,7 +149,7 @@ class TimelineEventContentMapper( ) } is TimelineItemContent.CallInvite -> LegacyCallInviteContent - is TimelineItemContent.CallNotify -> CallNotifyContent + is TimelineItemContent.RtcNotification -> CallNotifyContent } } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt index 8aca65bf91..8360a1b06e 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt @@ -107,6 +107,7 @@ class DefaultCallNotificationEventResolver( callNotifyType = content.type, senderId = content.senderId, senderAvatarUrl = senderAvatarUrl, + expirationTimestamp = content.expirationTimestampMillis, ) } else { Timber.d("Event $eventId is call notify but should not ring: $isRoomCallActive, notify: ${content.type}") @@ -124,7 +125,7 @@ class DefaultCallNotificationEventResolver( roomIsDm = isDm, roomAvatarPath = roomAvatarUrl, senderAvatarPath = senderAvatarUrl, - type = EventType.CALL_NOTIFY, + type = EventType.RTC_NOTIFICATION, ) } } 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 3c6a1adbbb..3f07e12691 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 @@ -123,7 +123,7 @@ class DefaultNotificationCreator( val smallIcon = CommonDrawables.ic_notification - val containsMissedCall = events.any { it.type == EventType.CALL_NOTIFY } + val containsMissedCall = events.any { it.type == EventType.RTC_NOTIFICATION } val channelId = if (containsMissedCall) { notificationChannels.getChannelForIncomingCall(false) } else { @@ -213,8 +213,8 @@ class DefaultNotificationCreator( } setDeleteIntent(pendingIntentFactory.createDismissRoomPendingIntent(roomInfo.sessionId, roomInfo.roomId)) - // If any of the events are of call notify type it means a missed call, set the category to the right value - if (events.any { it.type == EventType.CALL_NOTIFY }) { + // If any of the events are of rtc notification type it means a missed call, set the category to the right value + if (events.any { it.type == EventType.RTC_NOTIFICATION }) { setCategory(NotificationCompat.CATEGORY_MISSED_CALL) } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableRingingCallEvent.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableRingingCallEvent.kt index 07e85ab2bf..4083af63f4 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableRingingCallEvent.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableRingingCallEvent.kt @@ -29,4 +29,5 @@ data class NotifiableRingingCallEvent( val roomAvatarUrl: String? = null, val callNotifyType: CallNotifyType, val timestamp: Long, + val expirationTimestamp: Long, ) : NotifiableEvent diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt index 9dafe93569..d251948992 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt @@ -296,6 +296,7 @@ class DefaultPushHandler( senderName = notifiableEvent.senderDisambiguatedDisplayName, avatarUrl = notifiableEvent.roomAvatarUrl, timestamp = notifiableEvent.timestamp, + expirationTimestamp = notifiableEvent.expirationTimestamp, notificationChannelId = notificationChannels.getChannelForIncomingCall(ring = true), textContent = notifiableEvent.description, ) From d350a553a95aec124951fdc1ffc36900558f6bc6 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 17 Sep 2025 15:28:48 +0200 Subject: [PATCH 080/145] bump rust component version --- gradle/libs.versions.toml | 2 +- .../notification/TimelineEventToNotificationContentMapper.kt | 2 +- .../android/libraries/matrix/impl/timeline/RustTimeline.kt | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 49d7b3996c..771d912e6d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -176,7 +176,7 @@ jsoup = "org.jsoup:jsoup:1.21.2" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.1.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.16" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.17" 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/notification/TimelineEventToNotificationContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt index 98cf2f7fc9..8d019c7ba1 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 @@ -106,6 +106,6 @@ private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationCon } private fun RtcNotificationType.map(): CallNotifyType = when (this) { - RtcNotificationType.NOTIFY -> CallNotifyType.NOTIFY + RtcNotificationType.NOTIFICATION -> CallNotifyType.NOTIFY RtcNotificationType.RING -> CallNotifyType.RING } 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 9e1ade63a6..b4888dafe0 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 @@ -437,7 +437,6 @@ class RustTimeline( key = emoji, itemId = eventOrTransactionId.toRustEventOrTransactionId(), ) - return@runCatchingExceptions Unit } } From b26fa73e8d9937827f385a468221350a2fab633f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 17 Sep 2025 15:30:42 +0200 Subject: [PATCH 081/145] Dependency: extract the Matrix SDK and add instructions for upgrading the library. --- gradle/libs.versions.toml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 49d7b3996c..75d6157102 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -160,6 +160,14 @@ test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScan test_detekt_api = { module = "io.gitlab.arturbosch.detekt:detekt-api", version.ref = "detekt" } test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version.ref = "detekt" } +# Matrix SDK +# When upgrading the library, you may want to check what's new in the FFI layer by having a look to the +# latest commits from the history of this file: +# https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt +# All new features should not be implemented in the pull request that upgrades the version, developers should +# only fix API breaks and may add some TODOs. +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.16" + # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } coil_network_okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coil" } @@ -176,7 +184,6 @@ jsoup = "org.jsoup:jsoup:1.21.2" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.1.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.16" 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 277602f2bcdbf1e38f2db0057cbb3f465b405739 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 17 Sep 2025 15:53:14 +0200 Subject: [PATCH 082/145] fix test compilation --- .../android/features/call/test/CallNotificationData.kt | 2 ++ .../features/call/test/FakeElementCallEntryPoint.kt | 1 + .../DefaultCallNotificationEventResolverTest.kt | 7 ++++--- .../notifications/DefaultNotifiableEventResolverTest.kt | 5 +++-- .../impl/notifications/fixtures/NotifiableEventFixture.kt | 2 ++ .../libraries/push/impl/push/DefaultPushHandlerTest.kt | 2 +- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt b/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt index 8e6ee00a16..d8b67c9aa7 100644 --- a/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt +++ b/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt @@ -30,6 +30,7 @@ fun aCallNotificationData( avatarUrl: String? = AN_AVATAR_URL, notificationChannelId: String = "channel_id", timestamp: Long = 0L, + expirationTimestamp: Long = 0L, textContent: String? = null, ): CallNotificationData = CallNotificationData( sessionId = sessionId, @@ -41,5 +42,6 @@ fun aCallNotificationData( avatarUrl = avatarUrl, notificationChannelId = notificationChannelId, timestamp = timestamp, + expirationTimestamp = expirationTimestamp, textContent = textContent, ) diff --git a/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt b/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt index 09a1269259..cd2e617b4d 100644 --- a/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt +++ b/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt @@ -38,6 +38,7 @@ class FakeElementCallEntryPoint( senderName: String?, avatarUrl: String?, timestamp: Long, + expirationTimestamp: Long, notificationChannelId: String, textContent: String?, ) { diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt index c9ebbb72b3..147847353b 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt @@ -61,11 +61,12 @@ class DefaultCallNotificationEventResolverTest { isUpdated = false, senderDisambiguatedDisplayName = A_USER_NAME_2, senderAvatarUrl = null, + expirationTimestamp = 1567L, callNotifyType = CallNotifyType.RING, ) val notificationData = aNotificationData( - content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.RING) + content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.RING, 1567) ) val result = resolver.resolveEvent(A_SESSION_ID, notificationData) assertThat(result.getOrNull()).isEqualTo(expectedResult) @@ -109,7 +110,7 @@ class DefaultCallNotificationEventResolverTest { ) val notificationData = aNotificationData( - content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.NOTIFY) + content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.NOTIFY, 0) ) val result = resolver.resolveEvent(A_SESSION_ID, notificationData) assertThat(result.getOrNull()).isEqualTo(expectedResult) @@ -153,7 +154,7 @@ class DefaultCallNotificationEventResolverTest { ) val notificationData = aNotificationData( - content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.RING) + content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.RING, 0) ) val result = resolver.resolveEvent(A_SESSION_ID, notificationData) assertThat(result.getOrNull()).isEqualTo(expectedResult) 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 2d99e31d74..4eccde3e76 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 @@ -695,7 +695,8 @@ class DefaultNotifiableEventResolverTest { AN_EVENT_ID to Result.success(aNotificationData( content = NotificationContent.MessageLike.CallNotify( A_USER_ID_2, - CallNotifyType.NOTIFY + CallNotifyType.NOTIFY, + 0 ), )) ) @@ -719,7 +720,7 @@ class DefaultNotifiableEventResolverTest { isRedacted = false, imageUriString = null, imageMimeType = null, - type = EventType.CALL_NOTIFY, + type = EventType.RTC_NOTIFICATION, ) ) callNotificationEventResolver.resolveEventLambda = { _, _, _ -> Result.success(expectedResult.notifiableEvent) } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt index b926806bcd..7cd63c1877 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt @@ -121,6 +121,7 @@ fun aNotifiableCallEvent( senderAvatarUrl: String? = AN_AVATAR_URL, callNotifyType: CallNotifyType = CallNotifyType.NOTIFY, timestamp: Long = 0L, + expirationTimestamp: Long = 0L, ) = NotifiableRingingCallEvent( sessionId = sessionId, eventId = eventId, @@ -129,6 +130,7 @@ fun aNotifiableCallEvent( editedEventId = null, description = "description", timestamp = timestamp, + expirationTimestamp = expirationTimestamp, canBeReplaced = false, isRedacted = false, isUpdated = false, 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 a070156d05..522c6a3c8c 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 @@ -440,7 +440,7 @@ class DefaultPushHandlerTest { onNotifiableEventsReceived = onNotifiableEventsReceived, notifiableEventsResult = { _, _ -> val request = NotificationEventRequest(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID, A_PUSHER_INFO) - Result.success(mapOf(request to Result.success(ResolvedPushEvent.Event(aNotifiableMessageEvent(type = EventType.CALL_NOTIFY))))) + Result.success(mapOf(request to Result.success(ResolvedPushEvent.Event(aNotifiableMessageEvent(type = EventType.RTC_NOTIFICATION))))) }, incrementPushCounterResult = {}, pushClientSecret = FakePushClientSecret( From 1ffdf74ca9e61bc459e30d6e7d314642cc08167e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Sep 2025 20:35:43 +0000 Subject: [PATCH 083/145] Update dependencyAnalysis to v3 --- 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 49d7b3996c..c82c12f344 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -48,7 +48,7 @@ telephoto = "0.16.0" haze = "1.6.10" # Dependency analysis -dependencyAnalysis = "2.19.0" +dependencyAnalysis = "3.0.4" # DI metro = "0.6.4" From be5244708fc1f45f5f8f31cb3a213e214d69667e Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 18 Sep 2025 09:18:36 +0200 Subject: [PATCH 084/145] review + tests --- features/call/impl/build.gradle.kts | 1 + .../notifications/CallNotificationData.kt | 1 + .../call/impl/utils/ActiveCallManager.kt | 4 +- .../call/DefaultElementCallEntryPointTest.kt | 1 + .../RingingCallNotificationCreatorTest.kt | 1 + .../utils/DefaultActiveCallManagerTest.kt | 81 +++++++++++++++++++ 6 files changed, 88 insertions(+), 1 deletion(-) diff --git a/features/call/impl/build.gradle.kts b/features/call/impl/build.gradle.kts index 0c9ae5a4b0..7d6cc745d0 100644 --- a/features/call/impl/build.gradle.kts +++ b/features/call/impl/build.gradle.kts @@ -100,6 +100,7 @@ dependencies { testImplementation(projects.libraries.push.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.appnavstate.test) + testImplementation(projects.services.toolbox.test) testImplementation(projects.tests.testutils) testImplementation(libs.androidx.compose.ui.test.junit) testReleaseImplementation(libs.androidx.compose.ui.test.manifest) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt index 8ebb8b8080..0bfbfb0411 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt @@ -26,5 +26,6 @@ data class CallNotificationData( val notificationChannelId: String, val timestamp: Long, val textContent: String?, + // Expiration timestamp in millis since epoch val expirationTimestamp: Long, ) : Parcelable diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index b609bfcbce..4006ede376 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -34,6 +34,7 @@ import io.element.android.libraries.push.api.notifications.ForegroundServiceType import io.element.android.libraries.push.api.notifications.NotificationIdProvider import io.element.android.libraries.push.api.notifications.OnMissedCallNotificationHandler import io.element.android.services.appnavstate.api.AppForegroundStateService +import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job @@ -98,6 +99,7 @@ class DefaultActiveCallManager( private val defaultCurrentCallService: DefaultCurrentCallService, private val appForegroundStateService: AppForegroundStateService, private val imageLoaderHolder: ImageLoaderHolder, + private val systemClock: SystemClock, ) : ActiveCallManager { private val tag = "DefaultActiveCallManager" private var timedOutCallJob: Job? = null @@ -120,7 +122,7 @@ class DefaultActiveCallManager( mutex.withLock { val ringDuration = min( - notificationData.expirationTimestamp - System.currentTimeMillis(), + notificationData.expirationTimestamp - systemClock.epochMillis(), ElementCallConfig.RINGING_CALL_DURATION_SECONDS * 1000L ) diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt index 86d9b80d65..7d0f15b540 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt @@ -59,6 +59,7 @@ class DefaultElementCallEntryPointTest { senderName = "senderName", avatarUrl = "avatarUrl", timestamp = 0, + expirationTimestamp = 0, notificationChannelId = "notificationChannelId", textContent = "textContent", ) diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/notifications/RingingCallNotificationCreatorTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/notifications/RingingCallNotificationCreatorTest.kt index f36267a353..0af482fc49 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/notifications/RingingCallNotificationCreatorTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/notifications/RingingCallNotificationCreatorTest.kt @@ -73,6 +73,7 @@ class RingingCallNotificationCreatorTest { roomAvatarUrl = "https://example.com/avatar.jpg", notificationChannelId = "channelId", timestamp = 0L, + expirationTimestamp = 20L, textContent = "textContent", ) diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt index d842126c67..3d1c35df4d 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt @@ -39,6 +39,8 @@ import io.element.android.libraries.push.test.notifications.FakeImageLoaderHolde import io.element.android.libraries.push.test.notifications.FakeOnMissedCallNotificationHandler import io.element.android.libraries.push.test.notifications.push.FakeNotificationBitmapLoader import io.element.android.services.appnavstate.test.FakeAppForegroundStateService +import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.plantTestTimber @@ -368,6 +370,83 @@ class DefaultActiveCallManagerTest { assertThat(manager.activeCall.value).isNotNull() } + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `IncomingCall - rings no longer than expiration time`() = runTest { + setupShadowPowerManager() + val notificationManagerCompat = mockk(relaxed = true) + val clock = FakeSystemClock() + val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat, systemClock = clock) + + assertThat(manager.activeWakeLock?.isHeld).isFalse() + assertThat(manager.activeCall.value).isNull() + + val eventTimestamp = A_FAKE_TIMESTAMP + // The call should not ring more than 30 seconds after the initial event was sent + val expirationTimestamp = eventTimestamp + 30_000 + + val callNotificationData = aCallNotificationData( + timestamp = eventTimestamp, + expirationTimestamp = expirationTimestamp, + ) + + // suppose it took 10s to be notified + clock.epochMillisResult = eventTimestamp + 10_000 + manager.registerIncomingCall(callNotificationData) + + assertThat(manager.activeCall.value).isEqualTo( + ActiveCall( + callType = CallType.RoomCall( + sessionId = callNotificationData.sessionId, + roomId = callNotificationData.roomId, + ), + callState = CallState.Ringing(callNotificationData) + ) + ) + + runCurrent() + + assertThat(manager.activeWakeLock?.isHeld).isTrue() + verify { notificationManagerCompat.notify(notificationId, any()) } + + // advance by 21s it should have stopped ringing + advanceTimeBy(21_000) + runCurrent() + + verify { notificationManagerCompat.cancel(any()) } + } + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `IncomingCall - ignore expired ring lifetime`() = runTest { + setupShadowPowerManager() + val notificationManagerCompat = mockk(relaxed = true) + val clock = FakeSystemClock() + val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat, systemClock = clock) + + assertThat(manager.activeWakeLock?.isHeld).isFalse() + assertThat(manager.activeCall.value).isNull() + + val eventTimestamp = A_FAKE_TIMESTAMP + // The call should not ring more than 30 seconds after the initial event was sent + val expirationTimestamp = eventTimestamp + 30_000 + + val callNotificationData = aCallNotificationData( + timestamp = eventTimestamp, + expirationTimestamp = expirationTimestamp, + ) + + // suppose it took 35s to be notified + clock.epochMillisResult = eventTimestamp + 35_000 + manager.registerIncomingCall(callNotificationData) + + assertThat(manager.activeCall.value).isNull() + + runCurrent() + + assertThat(manager.activeWakeLock?.isHeld).isFalse() + verify(exactly = 0) { notificationManagerCompat.notify(notificationId, any()) } + } + private fun setupShadowPowerManager() { shadowOf(InstrumentationRegistry.getInstrumentation().targetContext.getSystemService()).apply { setIsWakeLockLevelSupported(PowerManager.PARTIAL_WAKE_LOCK, true) @@ -378,6 +457,7 @@ class DefaultActiveCallManagerTest { matrixClientProvider: FakeMatrixClientProvider = FakeMatrixClientProvider(), onMissedCallNotificationHandler: FakeOnMissedCallNotificationHandler = FakeOnMissedCallNotificationHandler(), notificationManagerCompat: NotificationManagerCompat = mockk(relaxed = true), + systemClock: FakeSystemClock = FakeSystemClock(), ) = DefaultActiveCallManager( context = InstrumentationRegistry.getInstrumentation().targetContext, coroutineScope = backgroundScope, @@ -393,5 +473,6 @@ class DefaultActiveCallManagerTest { defaultCurrentCallService = DefaultCurrentCallService(), appForegroundStateService = FakeAppForegroundStateService(), imageLoaderHolder = FakeImageLoaderHolder(), + systemClock = systemClock, ) } From 1a7ce368b759445b9e5f610715e1c674625a22d5 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 18 Sep 2025 09:25:13 +0200 Subject: [PATCH 085/145] refactor: rename CallNotify to RtcNotification to match new event --- .../features/call/impl/utils/ActiveCallManager.kt | 2 +- .../matrix/api/notification/NotificationData.kt | 6 +++--- .../TimelineEventToNotificationContentMapper.kt | 10 +++++----- .../notifications/CallNotificationEventResolver.kt | 10 +++++----- .../notifications/DefaultNotifiableEventResolver.kt | 2 +- .../notifications/model/NotifiableRingingCallEvent.kt | 4 ++-- .../DefaultCallNotificationEventResolverTest.kt | 10 +++++----- .../DefaultNotifiableEventResolverTest.kt | 6 +++--- .../notifications/fixtures/NotifiableEventFixture.kt | 6 +++--- .../libraries/push/impl/push/DefaultPushHandlerTest.kt | 4 ++-- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index 4006ede376..34f46d1ea0 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -133,7 +133,7 @@ class DefaultActiveCallManager( } appForegroundStateService.updateHasRingingCall(true) - Timber.tag(tag).d("Received incoming call for room id: ${notificationData.roomId}, ringDuration: $ringDuration") + Timber.tag(tag).d("Received incoming call for room id: ${notificationData.roomId}, ringDuration(ms): $ringDuration") if (activeCall.value != null) { displayMissedCallNotification(notificationData) Timber.tag(tag).w("Already have an active call, ignoring incoming call: $notificationData") 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 61195b68cc..1a58ced0fd 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 @@ -49,9 +49,9 @@ sealed interface NotificationContent { val senderId: UserId, ) : MessageLike - data class CallNotify( + data class RtcNotification( val senderId: UserId, - val type: CallNotifyType, + val type: RtcNotificationType, val expirationTimestampMillis: Long ) : MessageLike @@ -119,7 +119,7 @@ sealed interface NotificationContent { ) : NotificationContent } -enum class CallNotifyType { +enum class RtcNotificationType { RING, NOTIFY } 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 8d019c7ba1..30935b882e 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 @@ -10,7 +10,7 @@ package io.element.android.libraries.matrix.impl.notification import io.element.android.libraries.core.extensions.runCatchingExceptions 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.notification.CallNotifyType +import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper import io.element.android.libraries.matrix.impl.timeline.item.event.EventMessageMapper @@ -78,7 +78,7 @@ private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationCon MessageLikeEventContent.CallCandidates -> NotificationContent.MessageLike.CallCandidates MessageLikeEventContent.CallHangup -> NotificationContent.MessageLike.CallHangup MessageLikeEventContent.CallInvite -> NotificationContent.MessageLike.CallInvite(senderId) - is MessageLikeEventContent.RtcNotification -> NotificationContent.MessageLike.CallNotify( + is MessageLikeEventContent.RtcNotification -> NotificationContent.MessageLike.RtcNotification( senderId = senderId, type = notificationType.map(), expirationTimestampMillis = expirationTs.toLong() @@ -105,7 +105,7 @@ private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationCon } } -private fun RtcNotificationType.map(): CallNotifyType = when (this) { - RtcNotificationType.NOTIFICATION -> CallNotifyType.NOTIFY - RtcNotificationType.RING -> CallNotifyType.RING +private fun RtcNotificationType.map(): RtcNotificationType = when (this) { + RtcNotificationType.NOTIFICATION -> RtcNotificationType.NOTIFY + RtcNotificationType.RING -> RtcNotificationType.RING } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt index 8360a1b06e..c1b9876948 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt @@ -14,7 +14,7 @@ import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.exception.NotificationResolverException -import io.element.android.libraries.matrix.api.notification.CallNotifyType +import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.api.notification.NotificationData import io.element.android.libraries.matrix.api.timeline.item.event.EventType @@ -58,13 +58,13 @@ class DefaultCallNotificationEventResolver( notificationData: NotificationData, forceNotify: Boolean ): Result = runCatchingExceptions { - val content = notificationData.content as? NotificationContent.MessageLike.CallNotify + val content = notificationData.content as? NotificationContent.MessageLike.RtcNotification ?: throw NotificationResolverException.UnknownError("content is not a call notify") val previousRingingCallStatus = appForegroundStateService.hasRingingCall.value // We need the sync service working to get the updated room info val isRoomCallActive = runCatchingExceptions { - if (content.type == CallNotifyType.RING) { + if (content.type == RtcNotificationType.RING) { appForegroundStateService.updateHasRingingCall(true) val client = clientProvider.getOrRestore( @@ -90,7 +90,7 @@ class DefaultCallNotificationEventResolver( }.getOrDefault(false) notificationData.run { - if (content.type == CallNotifyType.RING && isRoomCallActive && !forceNotify) { + if (content.type == RtcNotificationType.RING && isRoomCallActive && !forceNotify) { NotifiableRingingCallEvent( sessionId = sessionId, roomId = roomId, @@ -104,7 +104,7 @@ class DefaultCallNotificationEventResolver( description = stringProvider.getString(R.string.notification_incoming_call), senderDisambiguatedDisplayName = getDisambiguatedDisplayName(content.senderId), roomAvatarUrl = roomAvatarUrl, - callNotifyType = content.type, + rtcNotificationType = content.type, senderId = content.senderId, senderAvatarUrl = senderAvatarUrl, expirationTimestamp = content.expirationTimestampMillis, 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 6fa5366586..38a1d4f753 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 @@ -199,7 +199,7 @@ class DefaultNotifiableEventResolver( ) ResolvedPushEvent.Event(notifiableMessageEvent) } - is NotificationContent.MessageLike.CallNotify -> { + is NotificationContent.MessageLike.RtcNotification -> { val notifiableEvent = callNotificationEventResolver.resolveEvent(userId, this).getOrThrow() ResolvedPushEvent.Event(notifiableEvent) } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableRingingCallEvent.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableRingingCallEvent.kt index 4083af63f4..7d92ad3a8b 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableRingingCallEvent.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableRingingCallEvent.kt @@ -11,7 +11,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.notification.CallNotifyType +import io.element.android.libraries.matrix.api.notification.RtcNotificationType data class NotifiableRingingCallEvent( override val sessionId: SessionId, @@ -27,7 +27,7 @@ data class NotifiableRingingCallEvent( val senderDisambiguatedDisplayName: String?, val senderAvatarUrl: String?, val roomAvatarUrl: String? = null, - val callNotifyType: CallNotifyType, + val rtcNotificationType: RtcNotificationType, val timestamp: Long, val expirationTimestamp: Long, ) : NotifiableEvent diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt index 147847353b..21a30a60ff 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt @@ -8,7 +8,7 @@ package io.element.android.libraries.push.impl.notifications import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.notification.CallNotifyType +import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ID @@ -62,11 +62,11 @@ class DefaultCallNotificationEventResolverTest { senderDisambiguatedDisplayName = A_USER_NAME_2, senderAvatarUrl = null, expirationTimestamp = 1567L, - callNotifyType = CallNotifyType.RING, + rtcNotificationType = RtcNotificationType.RING, ) val notificationData = aNotificationData( - content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.RING, 1567) + content = NotificationContent.MessageLike.RtcNotification(A_USER_ID_2, RtcNotificationType.RING, 1567) ) val result = resolver.resolveEvent(A_SESSION_ID, notificationData) assertThat(result.getOrNull()).isEqualTo(expectedResult) @@ -110,7 +110,7 @@ class DefaultCallNotificationEventResolverTest { ) val notificationData = aNotificationData( - content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.NOTIFY, 0) + content = NotificationContent.MessageLike.RtcNotification(A_USER_ID_2, RtcNotificationType.NOTIFY, 0) ) val result = resolver.resolveEvent(A_SESSION_ID, notificationData) assertThat(result.getOrNull()).isEqualTo(expectedResult) @@ -154,7 +154,7 @@ class DefaultCallNotificationEventResolverTest { ) val notificationData = aNotificationData( - content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.RING, 0) + content = NotificationContent.MessageLike.RtcNotification(A_USER_ID_2, RtcNotificationType.RING, 0) ) val result = resolver.resolveEvent(A_SESSION_ID, notificationData) assertThat(result.getOrNull()).isEqualTo(expectedResult) 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 4eccde3e76..42806e2f99 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 @@ -12,7 +12,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.exception.NotificationResolverException import io.element.android.libraries.matrix.api.media.MediaSource -import io.element.android.libraries.matrix.api.notification.CallNotifyType +import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.api.notification.NotificationData import io.element.android.libraries.matrix.api.room.RoomMembershipState @@ -693,9 +693,9 @@ class DefaultNotifiableEventResolverTest { notificationResult = Result.success( mapOf( AN_EVENT_ID to Result.success(aNotificationData( - content = NotificationContent.MessageLike.CallNotify( + content = NotificationContent.MessageLike.RtcNotification( A_USER_ID_2, - CallNotifyType.NOTIFY, + RtcNotificationType.NOTIFY, 0 ), )) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt index 7cd63c1877..0d466d90fd 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt @@ -12,7 +12,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.UserId -import io.element.android.libraries.matrix.api.notification.CallNotifyType +import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.timeline.item.event.EventType import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_EVENT_ID @@ -119,7 +119,7 @@ fun aNotifiableCallEvent( senderName: String? = null, roomAvatarUrl: String? = AN_AVATAR_URL, senderAvatarUrl: String? = AN_AVATAR_URL, - callNotifyType: CallNotifyType = CallNotifyType.NOTIFY, + rtcNotificationType: RtcNotificationType = RtcNotificationType.NOTIFY, timestamp: Long = 0L, expirationTimestamp: Long = 0L, ) = NotifiableRingingCallEvent( @@ -138,5 +138,5 @@ fun aNotifiableCallEvent( senderId = senderId, roomAvatarUrl = roomAvatarUrl, senderAvatarUrl = senderAvatarUrl, - callNotifyType = callNotifyType, + rtcNotificationType = rtcNotificationType, ) 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 522c6a3c8c..91c1293220 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 @@ -20,7 +20,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.UserId import io.element.android.libraries.matrix.api.exception.NotificationResolverException -import io.element.android.libraries.matrix.api.notification.CallNotifyType +import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.timeline.item.event.EventType import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID_2 @@ -388,7 +388,7 @@ class DefaultPushHandlerTest { mapOf( request to Result.success( ResolvedPushEvent.Event( - aNotifiableCallEvent(callNotifyType = CallNotifyType.RING, timestamp = Instant.now().toEpochMilli()) + aNotifiableCallEvent(rtcNotificationType = RtcNotificationType.RING, timestamp = Instant.now().toEpochMilli()) ) ) ) From 6052d453fe98ab617b424e27fa20d27c3eff5849 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 18 Sep 2025 12:25:28 +0200 Subject: [PATCH 086/145] fix Conflicting import --- .../TimelineEventToNotificationContentMapper.kt | 10 +++++----- .../notifications/CallNotificationEventResolver.kt | 2 +- .../DefaultCallNotificationEventResolverTest.kt | 2 +- .../DefaultNotifiableEventResolverTest.kt | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) 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 30935b882e..2ca4a3c823 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 @@ -10,16 +10,16 @@ package io.element.android.libraries.matrix.impl.notification import io.element.android.libraries.core.extensions.runCatchingExceptions 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.notification.RtcNotificationType import io.element.android.libraries.matrix.api.notification.NotificationContent +import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper import io.element.android.libraries.matrix.impl.timeline.item.event.EventMessageMapper import org.matrix.rustcomponents.sdk.MessageLikeEventContent -import org.matrix.rustcomponents.sdk.RtcNotificationType import org.matrix.rustcomponents.sdk.StateEventContent import org.matrix.rustcomponents.sdk.TimelineEvent import org.matrix.rustcomponents.sdk.TimelineEventType import org.matrix.rustcomponents.sdk.use +import org.matrix.rustcomponents.sdk.RtcNotificationType as SdkRtcNotificationType class TimelineEventToNotificationContentMapper { fun map(timelineEvent: TimelineEvent): Result { @@ -105,7 +105,7 @@ private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationCon } } -private fun RtcNotificationType.map(): RtcNotificationType = when (this) { - RtcNotificationType.NOTIFICATION -> RtcNotificationType.NOTIFY - RtcNotificationType.RING -> RtcNotificationType.RING +private fun SdkRtcNotificationType.map(): RtcNotificationType = when (this) { + SdkRtcNotificationType.NOTIFICATION -> RtcNotificationType.NOTIFY + SdkRtcNotificationType.RING -> RtcNotificationType.RING } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt index c1b9876948..689cc8a2ea 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/CallNotificationEventResolver.kt @@ -14,9 +14,9 @@ import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.exception.NotificationResolverException -import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.api.notification.NotificationData +import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.timeline.item.event.EventType import io.element.android.libraries.push.impl.R import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt index 21a30a60ff..a9d820b8cb 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt @@ -8,8 +8,8 @@ package io.element.android.libraries.push.impl.notifications import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.notification.NotificationContent +import io.element.android.libraries.matrix.api.notification.RtcNotificationType 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_ROOM_NAME 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 42806e2f99..25e6b92b16 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 @@ -12,9 +12,9 @@ import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.exception.NotificationResolverException import io.element.android.libraries.matrix.api.media.MediaSource -import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.api.notification.NotificationData +import io.element.android.libraries.matrix.api.notification.RtcNotificationType import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType From f7b7328fea1c34b4e59ba5f48261ccf30cf95c29 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 18 Sep 2025 12:58:36 +0200 Subject: [PATCH 087/145] Fix wrong expiration default that was breaking tests --- .../element/android/features/call/test/CallNotificationData.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt b/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt index d8b67c9aa7..2c56ab299b 100644 --- a/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt +++ b/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt @@ -30,7 +30,7 @@ fun aCallNotificationData( avatarUrl: String? = AN_AVATAR_URL, notificationChannelId: String = "channel_id", timestamp: Long = 0L, - expirationTimestamp: Long = 0L, + expirationTimestamp: Long = 30_000L, textContent: String? = null, ): CallNotificationData = CallNotificationData( sessionId = sessionId, From b13c93f3cd11d11e154b1df1c4fffc31f74d8520 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 18 Sep 2025 14:32:01 +0200 Subject: [PATCH 088/145] fix the tests --- .../messages/impl/actionlist/ActionListPresenterTest.kt | 4 ++-- .../android/libraries/matrix/api/room/MessageEventType.kt | 2 +- .../android/libraries/matrix/impl/room/MessageEventType.kt | 4 ++-- .../libraries/matrix/impl/fixtures/factories/SpaceRoom.kt | 1 + .../libraries/matrix/impl/room/MessageEventTypeKtTest.kt | 4 ++-- .../notifications/DefaultCallNotificationEventResolverTest.kt | 4 ++-- 6 files changed, 10 insertions(+), 9 deletions(-) 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 964143ac78..d6188e0e76 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 @@ -18,8 +18,8 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.timeline.aTimelineItemEvent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent @@ -1193,7 +1193,7 @@ class ActionListPresenterTest { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, - content = TimelineItemCallNotifyContent(), + content = TimelineItemRtcNotificationContent(), ) initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MessageEventType.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MessageEventType.kt index ce98ecfe6b..5d20840cf7 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MessageEventType.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MessageEventType.kt @@ -12,7 +12,7 @@ enum class MessageEventType { CALL_INVITE, CALL_HANGUP, CALL_CANDIDATES, - CALL_NOTIFY, + RTC_NOTIFICATION, KEY_VERIFICATION_READY, KEY_VERIFICATION_START, KEY_VERIFICATION_CANCEL, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt index 6c42152d83..4e88f0971e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventType.kt @@ -15,7 +15,7 @@ fun MessageEventType.map(): MessageLikeEventType = when (this) { MessageEventType.CALL_INVITE -> MessageLikeEventType.CALL_INVITE MessageEventType.CALL_HANGUP -> MessageLikeEventType.CALL_HANGUP MessageEventType.CALL_CANDIDATES -> MessageLikeEventType.CALL_CANDIDATES - MessageEventType.CALL_NOTIFY -> MessageLikeEventType.RTC_NOTIFICATION + MessageEventType.RTC_NOTIFICATION -> MessageLikeEventType.RTC_NOTIFICATION MessageEventType.KEY_VERIFICATION_READY -> MessageLikeEventType.KEY_VERIFICATION_READY MessageEventType.KEY_VERIFICATION_START -> MessageLikeEventType.KEY_VERIFICATION_START MessageEventType.KEY_VERIFICATION_CANCEL -> MessageLikeEventType.KEY_VERIFICATION_CANCEL @@ -41,7 +41,7 @@ fun MessageLikeEventType.map(): MessageEventType = when (this) { MessageLikeEventType.CALL_INVITE -> MessageEventType.CALL_INVITE MessageLikeEventType.CALL_HANGUP -> MessageEventType.CALL_HANGUP MessageLikeEventType.CALL_CANDIDATES -> MessageEventType.CALL_CANDIDATES - MessageLikeEventType.RTC_NOTIFICATION -> MessageEventType.CALL_NOTIFY + MessageLikeEventType.RTC_NOTIFICATION -> MessageEventType.RTC_NOTIFICATION MessageLikeEventType.KEY_VERIFICATION_READY -> MessageEventType.KEY_VERIFICATION_READY MessageLikeEventType.KEY_VERIFICATION_START -> MessageEventType.KEY_VERIFICATION_START MessageLikeEventType.KEY_VERIFICATION_CANCEL -> MessageEventType.KEY_VERIFICATION_CANCEL diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt index c699ef8097..01c5deca68 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt @@ -43,4 +43,5 @@ fun aRustSpaceRoom( childrenCount = childrenCount, state = state, heroes = heroes, + via = emptyList() ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt index 980aba75fa..75936ca0dc 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt @@ -19,7 +19,7 @@ class MessageEventTypeKtTest { assertThat(MessageLikeEventType.CALL_INVITE.map()).isEqualTo(MessageEventType.CALL_INVITE) assertThat(MessageLikeEventType.CALL_HANGUP.map()).isEqualTo(MessageEventType.CALL_HANGUP) assertThat(MessageLikeEventType.CALL_CANDIDATES.map()).isEqualTo(MessageEventType.CALL_CANDIDATES) - assertThat(MessageLikeEventType.CALL_NOTIFY.map()).isEqualTo(MessageEventType.CALL_NOTIFY) + assertThat(MessageLikeEventType.RTC_NOTIFICATION.map()).isEqualTo(MessageEventType.RTC_NOTIFICATION) assertThat(MessageLikeEventType.KEY_VERIFICATION_READY.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_READY) assertThat(MessageLikeEventType.KEY_VERIFICATION_START.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_START) assertThat(MessageLikeEventType.KEY_VERIFICATION_CANCEL.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_CANCEL) @@ -46,7 +46,7 @@ class MessageEventTypeKtTest { assertThat(MessageEventType.CALL_INVITE.map()).isEqualTo(MessageLikeEventType.CALL_INVITE) assertThat(MessageEventType.CALL_HANGUP.map()).isEqualTo(MessageLikeEventType.CALL_HANGUP) assertThat(MessageEventType.CALL_CANDIDATES.map()).isEqualTo(MessageLikeEventType.CALL_CANDIDATES) - assertThat(MessageEventType.CALL_NOTIFY.map()).isEqualTo(MessageLikeEventType.CALL_NOTIFY) + assertThat(MessageEventType.RTC_NOTIFICATION.map()).isEqualTo(MessageLikeEventType.RTC_NOTIFICATION) assertThat(MessageEventType.KEY_VERIFICATION_READY.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_READY) assertThat(MessageEventType.KEY_VERIFICATION_START.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_START) assertThat(MessageEventType.KEY_VERIFICATION_CANCEL.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_CANCEL) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt index a9d820b8cb..f9097752f1 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultCallNotificationEventResolverTest.kt @@ -106,7 +106,7 @@ class DefaultCallNotificationEventResolverTest { imageUriString = null, imageMimeType = null, threadId = null, - type = "m.call.notify", + type = "org.matrix.msc4075.rtc.notification", ) val notificationData = aNotificationData( @@ -150,7 +150,7 @@ class DefaultCallNotificationEventResolverTest { imageUriString = null, imageMimeType = null, threadId = null, - type = "m.call.notify", + type = "org.matrix.msc4075.rtc.notification", ) val notificationData = aNotificationData( From 4c7c0a4163efe1f9233d2a3729504720852bf8bc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Sep 2025 15:02:39 +0000 Subject: [PATCH 089/145] Update dependency org.matrix.rustcomponents:sdk-android to v25.9.18 (#5365) This contains important performance fixes for the room list. 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 771d912e6d..cb92afd834 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -176,7 +176,7 @@ jsoup = "org.jsoup:jsoup:1.21.2" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.1.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.17" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.18" 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 2af6895b9f1f68b376a3a47086b2d29ac1312a60 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Sep 2025 21:28:59 +0200 Subject: [PATCH 090/145] Fix compilation issues after merging develop. --- .../android/features/home/impl/DefaultHomeEntryPointTest.kt | 1 - .../features/messages/impl/DefaultMessagesEntryPointTest.kt | 1 + .../roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt | 1 + .../userprofile/impl/DefaultUserProfileEntryPointTest.kt | 1 + 4 files changed, 3 insertions(+), 1 deletion(-) diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt index 0eacd792c7..7d0c95befd 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt @@ -48,7 +48,6 @@ class DefaultHomeEntryPointTest { override fun onSessionConfirmRecoveryKeyClick() = lambdaError() override fun onRoomSettingsClick(roomId: RoomId) = lambdaError() override fun onReportBugClick() = lambdaError() - override fun onLogoutForNativeSlidingSyncMigrationNeeded() = lambdaError() } val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) .callback(callback) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt index cf98370ddc..a4753807cd 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt @@ -80,6 +80,7 @@ class DefaultMessagesEntryPointTest { senderName: String?, avatarUrl: String?, timestamp: Long, + expirationTimestamp: Long, notificationChannelId: String, textContent: String?, ) = lambdaError() diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt index 3c29ef5c2e..f2412e616b 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt @@ -63,6 +63,7 @@ class DefaultRoomDetailsEntryPointTest { senderName: String?, avatarUrl: String?, timestamp: Long, + expirationTimestamp: Long, notificationChannelId: String, textContent: String? ) = lambdaError() diff --git a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt index dbe5ed89f1..1537167d20 100644 --- a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt +++ b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt @@ -54,6 +54,7 @@ class DefaultUserProfileEntryPointTest { senderName: String?, avatarUrl: String?, timestamp: Long, + expirationTimestamp: Long, notificationChannelId: String, textContent: String? ) = lambdaError() From aa118f83a012edfe5eafd6a8ffec1b285f348c0f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Sep 2025 21:10:26 +0000 Subject: [PATCH 091/145] Update dependency com.google.firebase:firebase-bom to v34.3.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 eca610ae30..2f5c2057df 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -74,7 +74,7 @@ kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlin kover_gradle_plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" } ksp_gradle_plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } # https://firebase.google.com/docs/android/setup#available-libraries -google_firebase_bom = "com.google.firebase:firebase-bom:34.2.0" +google_firebase_bom = "com.google.firebase:firebase-bom:34.3.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" } ksp_plugin = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } From 1cc7afb585077cf67ae072952bab9c0329ec43c2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Sep 2025 10:48:39 +0200 Subject: [PATCH 092/145] Make PushData.clientSecret mandatory. Also do not restore the last session as a fallback, it can lead to error in a multi account context, or even when a ghost pusher send a Push. --- .../push/impl/push/DefaultPushHandler.kt | 27 ++------ .../push/impl/push/DefaultPushHandlerTest.kt | 62 +------------------ .../libraries/pushproviders/api/PushData.kt | 2 +- .../firebase/PushDataFirebase.kt | 3 +- .../firebase/FirebasePushParserTest.kt | 6 ++ 5 files changed, 16 insertions(+), 84 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt index d251948992..3a4cf4d6aa 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt @@ -16,7 +16,6 @@ import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.di.annotations.AppCoroutineScope -import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.exception.NotificationResolverException import io.element.android.libraries.push.impl.history.PushHistoryService import io.element.android.libraries.push.impl.history.onDiagnosticPush @@ -58,7 +57,6 @@ class DefaultPushHandler( private val userPushStoreFactory: UserPushStoreFactory, private val pushClientSecret: PushClientSecret, private val buildMeta: BuildMeta, - private val matrixAuthenticationService: MatrixAuthenticationService, private val diagnosticPushHandler: DiagnosticPushHandler, private val elementCallEntryPoint: ElementCallEntryPoint, private val notificationChannels: NotificationChannels, @@ -241,32 +239,15 @@ class DefaultPushHandler( } else { Timber.tag(loggerTag.value).d("## handleInternal()") } - val clientSecret = pushData.clientSecret - // clientSecret should not be null. If this happens, restore default session - var reason = if (clientSecret == null) "No client secret" else "" - val userId = clientSecret?.let { - // Get userId from client secret - pushClientSecret.getUserIdFromSecret(clientSecret).also { - if (it == null) { - reason = "Unable to get userId from client secret" - } - } - } - ?: run { - matrixAuthenticationService.getLatestSessionId().also { - if (it == null) { - if (reason.isNotEmpty()) reason += " - " - reason += "Unable to get latest sessionId" - } - } - } + // Get userId from client secret + val userId = pushClientSecret.getUserIdFromSecret(pushData.clientSecret) if (userId == null) { - Timber.w("Unable to get a session") + Timber.w("Unable to get userId from client secret") pushHistoryService.onUnableToRetrieveSession( providerInfo = providerInfo, eventId = pushData.eventId, roomId = pushData.roomId, - reason = reason, + reason = "Unable to get userId from client secret", ) return } 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 91c1293220..e482385b3d 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 @@ -14,7 +14,6 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.call.api.CallType import io.element.android.features.call.test.FakeElementCallEntryPoint import io.element.android.libraries.core.meta.BuildMeta -import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId @@ -28,7 +27,6 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SECRET import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_ID -import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.push.impl.history.FakePushHistoryService import io.element.android.libraries.push.impl.history.PushHistoryService @@ -181,7 +179,7 @@ class DefaultPushHandlerTest { } @Test - fun `when PushData is received, but client secret is not known, fallback the latest session`() = + fun `when PushData is received, but client secret is not known, nothing happen`() = runTest { val aNotifiableMessageEvent = aNotifiableMessageEvent() val notifiableEventResult = @@ -207,58 +205,6 @@ class DefaultPushHandlerTest { pushClientSecret = FakePushClientSecret( getUserIdFromSecretResult = { null } ), - matrixAuthenticationService = FakeMatrixAuthenticationService().apply { - getLatestSessionIdLambda = { A_USER_ID } - }, - incrementPushCounterResult = incrementPushCounterResult, - pushHistoryService = pushHistoryService, - ) - defaultPushHandler.handle(aPushData, A_PUSHER_INFO) - - advanceTimeBy(300.milliseconds) - - incrementPushCounterResult.assertions() - .isCalledOnce() - notifiableEventResult.assertions() - .isCalledOnce() - .with(value(A_USER_ID), any()) - onNotifiableEventsReceived.assertions() - .isCalledOnce() - .with(value(listOf(aNotifiableMessageEvent))) - onPushReceivedResult.assertions() - .isCalledOnce() - } - - @Test - fun `when PushData is received, but client secret is not known, and there is no latest session, nothing happen`() = - runTest { - val aNotifiableMessageEvent = aNotifiableMessageEvent() - val notifiableEventResult = - lambdaRecorder, Result>>> { _, _ -> - val request = NotificationEventRequest(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID, A_PUSHER_INFO) - Result.success(mapOf(request to Result.success(ResolvedPushEvent.Event(aNotifiableMessageEvent)))) - } - val onNotifiableEventsReceived = lambdaRecorder, Unit> {} - val incrementPushCounterResult = lambdaRecorder {} - val aPushData = PushData( - eventId = AN_EVENT_ID, - roomId = A_ROOM_ID, - unread = 0, - clientSecret = A_SECRET, - ) - val onPushReceivedResult = lambdaRecorder { _, _, _, _, _, _, _ -> } - val pushHistoryService = FakePushHistoryService( - onPushReceivedResult = onPushReceivedResult, - ) - val defaultPushHandler = createDefaultPushHandler( - onNotifiableEventsReceived = onNotifiableEventsReceived, - notifiableEventsResult = notifiableEventResult, - pushClientSecret = FakePushClientSecret( - getUserIdFromSecretResult = { null } - ), - matrixAuthenticationService = FakeMatrixAuthenticationService().apply { - getLatestSessionIdLambda = { null } - }, incrementPushCounterResult = incrementPushCounterResult, pushHistoryService = pushHistoryService, ) @@ -655,8 +601,8 @@ class DefaultPushHandlerTest { var receivedFallbackEvent = false val onPushReceivedResult = lambdaRecorder { _, _, _, _, isResolved, _, comment -> - receivedFallbackEvent = !isResolved && comment == "Unable to resolve event: ${aNotifiableFallbackEvent.cause}" - } + receivedFallbackEvent = !isResolved && comment == "Unable to resolve event: ${aNotifiableFallbackEvent.cause}" + } val pushHistoryService = FakePushHistoryService( onPushReceivedResult = onPushReceivedResult, ) @@ -694,7 +640,6 @@ class DefaultPushHandlerTest { userPushStore: UserPushStore = FakeUserPushStore(), pushClientSecret: PushClientSecret = FakePushClientSecret(), buildMeta: BuildMeta = aBuildMeta(), - matrixAuthenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), diagnosticPushHandler: DiagnosticPushHandler = DiagnosticPushHandler(), elementCallEntryPoint: FakeElementCallEntryPoint = FakeElementCallEntryPoint(), notificationChannels: FakeNotificationChannels = FakeNotificationChannels(), @@ -712,7 +657,6 @@ class DefaultPushHandlerTest { userPushStoreFactory = FakeUserPushStoreFactory { userPushStore }, pushClientSecret = pushClientSecret, buildMeta = buildMeta, - matrixAuthenticationService = matrixAuthenticationService, diagnosticPushHandler = diagnosticPushHandler, elementCallEntryPoint = elementCallEntryPoint, notificationChannels = notificationChannels, diff --git a/libraries/pushproviders/api/src/main/kotlin/io/element/android/libraries/pushproviders/api/PushData.kt b/libraries/pushproviders/api/src/main/kotlin/io/element/android/libraries/pushproviders/api/PushData.kt index e08ab1c18f..6000f74a95 100644 --- a/libraries/pushproviders/api/src/main/kotlin/io/element/android/libraries/pushproviders/api/PushData.kt +++ b/libraries/pushproviders/api/src/main/kotlin/io/element/android/libraries/pushproviders/api/PushData.kt @@ -22,5 +22,5 @@ data class PushData( val eventId: EventId, val roomId: RoomId, val unread: Int?, - val clientSecret: String?, + val clientSecret: String, ) diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/PushDataFirebase.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/PushDataFirebase.kt index 7bc1515332..fb33ab9c1f 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/PushDataFirebase.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/PushDataFirebase.kt @@ -34,10 +34,11 @@ data class PushDataFirebase( fun PushDataFirebase.toPushData(): PushData? { val safeEventId = eventId?.let(::EventId) ?: return null val safeRoomId = roomId?.let(::RoomId) ?: return null + val safeClientSecret = clientSecret ?: return null return PushData( eventId = safeEventId, roomId = safeRoomId, unread = unread, - clientSecret = clientSecret, + clientSecret = safeClientSecret, ) } diff --git a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/FirebasePushParserTest.kt b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/FirebasePushParserTest.kt index 71848fc4df..49ed5bc6d4 100644 --- a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/FirebasePushParserTest.kt +++ b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/FirebasePushParserTest.kt @@ -59,6 +59,12 @@ class FirebasePushParserTest { assertThrowsInDebug { pushParser.parse(FIREBASE_PUSH_DATA.mutate("event_id", "")) } } + @Test + fun `test empty client secret`() { + val pushParser = FirebasePushParser() + assertThat(pushParser.parse(FIREBASE_PUSH_DATA.mutate("cs", null))).isNull() + } + @Test fun `test invalid eventId`() { val pushParser = FirebasePushParser() From 6355feb96ddfaeadbbd5766ecf31f4d14242f59e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Sep 2025 17:27:53 +0200 Subject: [PATCH 093/145] Introduce BugReportFlowNode, and remove NavTarget.ViewLogs from RootFlowNode. --- appnav/build.gradle.kts | 1 - .../io/element/android/appnav/RootFlowNode.kt | 28 +----- .../api/bugreport/BugReportEntryPoint.kt | 3 +- features/rageshake/impl/build.gradle.kts | 1 + .../impl/bugreport/BugReportFlowNode.kt | 95 +++++++++++++++++++ .../rageshake/impl/bugreport/BugReportNode.kt | 16 ++-- .../bugreport/DefaultBugReportEntryPoint.kt | 2 +- .../DefaultBugReportEntryPointTest.kt | 18 ++-- 8 files changed, 121 insertions(+), 43 deletions(-) create mode 100644 features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportFlowNode.kt diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index ef97f92781..3ea6f9d1c9 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -43,7 +43,6 @@ dependencies { implementation(projects.features.ftue.api) implementation(projects.features.share.api) - implementation(projects.features.viewfolder.api) implementation(projects.services.apperror.impl) implementation(projects.services.appnavstate.api) 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 818e670e46..c67496ef87 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt @@ -39,7 +39,6 @@ import io.element.android.features.login.api.accesscontrol.AccountProviderAccess import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint import io.element.android.features.rageshake.api.reporter.BugReporter import io.element.android.features.signedout.api.SignedOutEntryPoint -import io.element.android.features.viewfolder.api.ViewFolderEntryPoint import io.element.android.libraries.architecture.BackstackView import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.createNode @@ -71,7 +70,6 @@ class RootFlowNode( private val matrixSessionCache: MatrixSessionCache, private val presenter: RootPresenter, private val bugReportEntryPoint: BugReportEntryPoint, - private val viewFolderEntryPoint: ViewFolderEntryPoint, private val signedOutEntryPoint: SignedOutEntryPoint, private val intentResolver: IntentResolver, private val oidcActionFlow: OidcActionFlow, @@ -200,11 +198,6 @@ class RootFlowNode( @Parcelize data object BugReport : NavTarget - - @Parcelize - data class ViewLogs( - val rootPath: String, - ) : NavTarget } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { @@ -244,31 +237,12 @@ class RootFlowNode( NavTarget.SplashScreen -> splashNode(buildContext) NavTarget.BugReport -> { val callback = object : BugReportEntryPoint.Callback { - override fun onBugReportSent() { - backstack.pop() - } - - override fun onViewLogs(basePath: String) { - backstack.push(NavTarget.ViewLogs(rootPath = basePath)) - } - } - bugReportEntryPoint - .nodeBuilder(this, buildContext) - .callback(callback) - .build() - } - is NavTarget.ViewLogs -> { - val callback = object : ViewFolderEntryPoint.Callback { override fun onDone() { backstack.pop() } } - val params = ViewFolderEntryPoint.Params( - rootPath = navTarget.rootPath, - ) - viewFolderEntryPoint + bugReportEntryPoint .nodeBuilder(this, buildContext) - .params(params) .callback(callback) .build() } diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/bugreport/BugReportEntryPoint.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/bugreport/BugReportEntryPoint.kt index fbc7eb0dc8..0eb84b529b 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/bugreport/BugReportEntryPoint.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/bugreport/BugReportEntryPoint.kt @@ -21,7 +21,6 @@ interface BugReportEntryPoint : FeatureEntryPoint { } interface Callback : Plugin { - fun onBugReportSent() - fun onViewLogs(basePath: String) + fun onDone() } } diff --git a/features/rageshake/impl/build.gradle.kts b/features/rageshake/impl/build.gradle.kts index 717da71e1f..b17d78f3aa 100644 --- a/features/rageshake/impl/build.gradle.kts +++ b/features/rageshake/impl/build.gradle.kts @@ -28,6 +28,7 @@ setupDependencyInjection() dependencies { implementation(projects.appconfig) implementation(projects.features.enterprise.api) + implementation(projects.features.viewfolder.api) implementation(projects.services.toolbox.api) implementation(projects.libraries.androidutils) implementation(projects.libraries.core) diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportFlowNode.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportFlowNode.kt new file mode 100644 index 0000000000..0dd4d4f518 --- /dev/null +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportFlowNode.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.rageshake.impl.bugreport + +import android.os.Parcelable +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 com.bumble.appyx.navmodel.backstack.BackStack +import com.bumble.appyx.navmodel.backstack.operation.pop +import com.bumble.appyx.navmodel.backstack.operation.push +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.Inject +import io.element.android.annotations.ContributesNode +import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint +import io.element.android.features.viewfolder.api.ViewFolderEntryPoint +import io.element.android.libraries.architecture.BackstackView +import io.element.android.libraries.architecture.BaseFlowNode +import io.element.android.libraries.architecture.createNode +import kotlinx.parcelize.Parcelize + +@ContributesNode(AppScope::class) +@Inject +class BugReportFlowNode( + @Assisted val buildContext: BuildContext, + @Assisted plugins: List, + private val viewFolderEntryPoint: ViewFolderEntryPoint, +) : BaseFlowNode( + backstack = BackStack( + initialElement = NavTarget.Root, + savedStateMap = buildContext.savedStateMap, + ), + buildContext = buildContext, + plugins = plugins +) { + private fun onDone() { + plugins().forEach { it.onDone() } + } + + sealed interface NavTarget : Parcelable { + @Parcelize + data object Root : NavTarget + + @Parcelize + data class ViewLogs( + val rootPath: String, + ) : NavTarget + } + + override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { + return when (navTarget) { + NavTarget.Root -> { + val callback = object : BugReportNode.Callback { + override fun onDone() { + this@BugReportFlowNode.onDone() + } + + override fun onViewLogs(basePath: String) { + backstack.push(NavTarget.ViewLogs(rootPath = basePath)) + } + } + createNode(buildContext, listOf(callback)) + } + is NavTarget.ViewLogs -> { + val callback = object : ViewFolderEntryPoint.Callback { + override fun onDone() { + backstack.pop() + } + } + val params = ViewFolderEntryPoint.Params( + rootPath = navTarget.rootPath, + ) + viewFolderEntryPoint + .nodeBuilder(this, buildContext) + .params(params) + .callback(callback) + .build() + } + } + } + + @Composable + override fun View(modifier: Modifier) { + BackstackView() + } +} diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportNode.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportNode.kt index 3f507829e8..b6eb494589 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportNode.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportNode.kt @@ -18,7 +18,6 @@ import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.Inject import io.element.android.annotations.ContributesNode -import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint import io.element.android.features.rageshake.api.reporter.BugReporter import io.element.android.libraries.androidutils.system.toast import io.element.android.libraries.ui.strings.CommonStrings @@ -31,8 +30,17 @@ class BugReportNode( private val presenter: BugReportPresenter, private val bugReporter: BugReporter, ) : Node(buildContext, plugins = plugins) { + interface Callback : Plugin { + fun onDone() + fun onViewLogs(basePath: String) + } + private fun onViewLogs(basePath: String) { - plugins().forEach { it.onViewLogs(basePath) } + plugins().forEach { it.onViewLogs(basePath) } + } + + private fun onDone() { + plugins().forEach { it.onDone() } } @Composable @@ -54,8 +62,4 @@ class BugReportNode( } ) } - - private fun onDone() { - plugins().forEach { it.onBugReportSent() } - } } diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPoint.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPoint.kt index 0415d36e1d..6fa5772c17 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPoint.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPoint.kt @@ -29,7 +29,7 @@ class DefaultBugReportEntryPoint : BugReportEntryPoint { } override fun build(): Node { - return parentNode.createNode(buildContext, plugins) + return parentNode.createNode(buildContext, plugins) } } } diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt index d76e8edb50..23d74f7247 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt @@ -9,8 +9,11 @@ package io.element.android.features.rageshake.impl.bugreport import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint +import io.element.android.features.viewfolder.api.ViewFolderEntryPoint import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest @@ -21,25 +24,28 @@ class DefaultBugReportEntryPointTest { @get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule() + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `test node builder`() = runTest { val entryPoint = DefaultBugReportEntryPoint() val parentNode = TestParentNode.create { buildContext, plugins -> - BugReportNode( + BugReportFlowNode( buildContext = buildContext, plugins = plugins, - presenter = createPresenter(), - bugReporter = FakeBugReporter(), + viewFolderEntryPoint = object : ViewFolderEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, ) } val callback = object : BugReportEntryPoint.Callback { - override fun onBugReportSent() = lambdaError() - override fun onViewLogs(basePath: String) = lambdaError() + override fun onDone() = lambdaError() } val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) .callback(callback) .build() - assertThat(result).isInstanceOf(BugReportNode::class.java) + assertThat(result).isInstanceOf(BugReportFlowNode::class.java) assertThat(result.plugins).contains(callback) } } From 6f06e6a6c33ce1d6565fa730116ba9465f0ad070 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Sep 2025 09:44:02 +0200 Subject: [PATCH 094/145] When logging out from Pin code screen, logout from all the sessions. --- .../impl/unlock/PinUnlockPresenter.kt | 2 +- .../features/logout/api/LogoutUseCase.kt | 10 +- features/logout/impl/build.gradle.kts | 1 + .../logout/impl/DefaultLogoutUseCase.kt | 31 +++-- .../logout/impl/DefaultLogoutUseCaseTest.kt | 120 ++++++++++++++++++ .../features/logout/test/FakeLogoutUseCase.kt | 2 +- 6 files changed, 146 insertions(+), 20 deletions(-) create mode 100644 features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCaseTest.kt 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 cf0f864f66..fc2e61d404 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 @@ -174,7 +174,7 @@ class PinUnlockPresenter( private fun CoroutineScope.signOut(signOutAction: MutableState>) = launch { suspend { - logoutUseCase.logout(ignoreSdkError = true) + logoutUseCase.logoutAll(ignoreSdkError = true) }.runCatchingUpdatingState(signOutAction) } } 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 6f265ec88c..3d980fe44b 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 @@ -8,16 +8,12 @@ package io.element.android.features.logout.api /** - * Used to trigger a log out of the current user from any part of the app. + * Used to trigger a log out of the current user(s) from any part of the app. */ interface LogoutUseCase { /** - * Log out the current user and then perform any needed cleanup tasks. + * Log out the current user(s) 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) - - interface Factory { - fun create(sessionId: String): LogoutUseCase - } + suspend fun logoutAll(ignoreSdkError: Boolean) } diff --git a/features/logout/impl/build.gradle.kts b/features/logout/impl/build.gradle.kts index b999d10db2..215c273913 100644 --- a/features/logout/impl/build.gradle.kts +++ b/features/logout/impl/build.gradle.kts @@ -39,4 +39,5 @@ dependencies { testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.libraries.sessionStorage.test) } 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 06a79a8d2d..52e295ba3e 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 @@ -12,22 +12,31 @@ import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Inject import io.element.android.features.logout.api.LogoutUseCase import io.element.android.libraries.matrix.api.MatrixClientProvider -import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.sessionstorage.api.SessionStore +import timber.log.Timber @ContributesBinding(AppScope::class) @Inject class DefaultLogoutUseCase( - private val authenticationService: MatrixAuthenticationService, + private val sessionStore: SessionStore, private val matrixClientProvider: MatrixClientProvider, ) : LogoutUseCase { - override suspend fun logout(ignoreSdkError: Boolean) { - val currentSession = authenticationService.getLatestSessionId() - if (currentSession != null) { - matrixClientProvider.getOrRestore(currentSession) - .getOrThrow() - .logout(userInitiated = true, ignoreSdkError = true) - } else { - error("No session to sign out") - } + override suspend fun logoutAll(ignoreSdkError: Boolean) { + sessionStore.getAllSessions() + .map { sessionData -> + SessionId(sessionData.userId) + } + .forEach { sessionId -> + Timber.d("Logging out sessionId: $sessionId") + matrixClientProvider.getOrRestore(sessionId).fold( + onSuccess = { client -> + client.logout(userInitiated = true, ignoreSdkError = ignoreSdkError) + }, + onFailure = { error -> + Timber.e(error, "Failed to get or restore MatrixClient for sessionId: $sessionId") + } + ) + } } } diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCaseTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCaseTest.kt new file mode 100644 index 0000000000..a17e7285de --- /dev/null +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutUseCaseTest.kt @@ -0,0 +1,120 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package io.element.android.features.logout.impl + +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.FakeMatrixClient +import io.element.android.libraries.matrix.test.FakeMatrixClientProvider +import io.element.android.libraries.sessionstorage.test.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class DefaultLogoutUseCaseTest { + @Test + fun `test logout from one session`() = runTest { + val logoutLambda1 = lambdaRecorder { _, _ -> } + val client1 = FakeMatrixClient(A_USER_ID).apply { + logoutLambda = logoutLambda1 + } + val sut = DefaultLogoutUseCase( + sessionStore = InMemorySessionStore( + initialList = listOf( + aSessionData(sessionId = A_USER_ID.value), + ) + ), + matrixClientProvider = FakeMatrixClientProvider( + getClient = { sessionId -> + when (sessionId) { + A_USER_ID -> Result.success(client1) + else -> error("Unexpected sessionId") + } + } + ), + ) + sut.logoutAll(ignoreSdkError = true) + logoutLambda1.assertions().isCalledOnce().with(value(true), value(true)) + } + + @Test + fun `test logout from several sessions`() = runTest { + val logoutLambda1 = lambdaRecorder { _, _ -> } + val logoutLambda2 = lambdaRecorder { _, _ -> } + val client1 = FakeMatrixClient(A_USER_ID).apply { + logoutLambda = logoutLambda1 + } + val client2 = FakeMatrixClient(A_USER_ID_2).apply { + logoutLambda = logoutLambda2 + } + val sut = DefaultLogoutUseCase( + sessionStore = InMemorySessionStore( + initialList = listOf( + aSessionData(sessionId = A_USER_ID.value), + aSessionData(sessionId = A_USER_ID_2.value), + ) + ), + matrixClientProvider = FakeMatrixClientProvider( + getClient = { sessionId -> + when (sessionId) { + A_USER_ID -> Result.success(client1) + A_USER_ID_2 -> Result.success(client2) + else -> error("Unexpected sessionId") + } + } + ), + ) + sut.logoutAll(ignoreSdkError = true) + logoutLambda1.assertions().isCalledOnce().with(value(true), value(true)) + logoutLambda2.assertions().isCalledOnce().with(value(true), value(true)) + } + + @Test + fun `test logout session not found is ignored`() = runTest { + val sut = DefaultLogoutUseCase( + sessionStore = InMemorySessionStore( + initialList = listOf( + aSessionData(sessionId = A_USER_ID.value), + ) + ), + matrixClientProvider = FakeMatrixClientProvider( + getClient = { sessionId -> + when (sessionId) { + A_USER_ID -> Result.failure(Exception("Session not found")) + else -> error("Unexpected sessionId") + } + } + ), + ) + sut.logoutAll(ignoreSdkError = true) + // No error + } + + @Test + fun `test logout no sessions`() = runTest { + val sut = DefaultLogoutUseCase( + sessionStore = InMemorySessionStore( + initialList = emptyList() + ), + matrixClientProvider = FakeMatrixClientProvider( + getClient = { sessionId -> + when (sessionId) { + else -> error("Unexpected sessionId") + } + } + ), + ) + sut.logoutAll(ignoreSdkError = true) + // No error + } +} diff --git a/features/logout/test/src/main/kotlin/io/element/android/features/logout/test/FakeLogoutUseCase.kt b/features/logout/test/src/main/kotlin/io/element/android/features/logout/test/FakeLogoutUseCase.kt index e71266b596..dd3ded4ef9 100644 --- a/features/logout/test/src/main/kotlin/io/element/android/features/logout/test/FakeLogoutUseCase.kt +++ b/features/logout/test/src/main/kotlin/io/element/android/features/logout/test/FakeLogoutUseCase.kt @@ -14,7 +14,7 @@ import io.element.android.tests.testutils.simulateLongTask class FakeLogoutUseCase( var logoutLambda: (Boolean) -> Unit = { lambdaError() } ) : LogoutUseCase { - override suspend fun logout(ignoreSdkError: Boolean) = simulateLongTask { + override suspend fun logoutAll(ignoreSdkError: Boolean) = simulateLongTask { logoutLambda(ignoreSdkError) } } From 65d682f8ca7e849455b928ef7f4fc2c5bcfa5993 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 27 Aug 2025 16:48:45 +0200 Subject: [PATCH 095/145] Rename method storeData to addSession. --- .../matrix/impl/auth/RustMatrixAuthenticationService.kt | 8 ++++---- .../android/libraries/sessionstorage/api/SessionStore.kt | 2 +- .../libraries/sessionstorage/impl/DatabaseSessionStore.kt | 2 +- .../sessionstorage/impl/DatabaseSessionStoreTest.kt | 4 ++-- .../impl/observer/DefaultSessionObserverTest.kt | 4 ++-- .../libraries/sessionstorage/test/InMemorySessionStore.kt | 2 +- 6 files changed, 11 insertions(+), 11 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 be2263eb86..b3300fb746 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 @@ -158,7 +158,7 @@ class RustMatrixAuthenticationService( ) val matrixClient = rustMatrixClientFactory.create(client) newMatrixClientObservers.forEach { it.invoke(matrixClient) } - sessionStore.storeData(sessionData) + sessionStore.addSession(sessionData) // Clean up the strong reference held here since it's no longer necessary currentClient = null @@ -182,7 +182,7 @@ class RustMatrixAuthenticationService( sessionPaths = currentSessionPaths, ) clear() - sessionStore.storeData(sessionData) + sessionStore.addSession(sessionData) SessionId(sessionData.userId) } } @@ -250,7 +250,7 @@ class RustMatrixAuthenticationService( val matrixClient = rustMatrixClientFactory.create(client) newMatrixClientObservers.forEach { it.invoke(matrixClient) } - sessionStore.storeData(sessionData) + sessionStore.addSession(sessionData) // Clean up the strong reference held here since it's no longer necessary currentClient = null @@ -295,7 +295,7 @@ class RustMatrixAuthenticationService( ) val matrixClient = rustMatrixClientFactory.create(client) newMatrixClientObservers.forEach { it.invoke(matrixClient) } - sessionStore.storeData(sessionData) + sessionStore.addSession(sessionData) // Clean up the strong reference held here since it's no longer necessary currentClient = null diff --git a/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionStore.kt b/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionStore.kt index a503ec0c28..74171c7a80 100644 --- a/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionStore.kt +++ b/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionStore.kt @@ -13,7 +13,7 @@ import kotlinx.coroutines.flow.map interface SessionStore { fun isLoggedIn(): Flow fun sessionsFlow(): Flow> - suspend fun storeData(sessionData: SessionData) + suspend fun addSession(sessionData: SessionData) /** * Will update the session data matching the userId, except the value of loginTimestamp. diff --git a/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStore.kt b/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStore.kt index 69f1fc41a5..72e2a41c57 100644 --- a/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStore.kt +++ b/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStore.kt @@ -49,7 +49,7 @@ class DatabaseSessionStore( } } - override suspend fun storeData(sessionData: SessionData) { + override suspend fun addSession(sessionData: SessionData) { sessionDataMutex.withLock { database.sessionDataQueries.insertSessionData(sessionData.toDbModel()) } diff --git a/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTest.kt b/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTest.kt index 0d74dde16a..bac797270d 100644 --- a/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTest.kt +++ b/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTest.kt @@ -44,10 +44,10 @@ class DatabaseSessionStoreTest { } @Test - fun `storeData persists the SessionData into the DB`() = runTest { + fun `addSession persists the SessionData into the DB`() = runTest { assertThat(database.sessionDataQueries.selectFirst().executeAsOneOrNull()).isNull() - databaseSessionStore.storeData(aSessionData.toApiModel()) + databaseSessionStore.addSession(aSessionData.toApiModel()) assertThat(database.sessionDataQueries.selectFirst().executeAsOneOrNull()).isEqualTo(aSessionData) assertThat(database.sessionDataQueries.selectAll().executeAsList().size).isEqualTo(1) diff --git a/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/observer/DefaultSessionObserverTest.kt b/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/observer/DefaultSessionObserverTest.kt index 35d7fea042..8b0184fdc7 100644 --- a/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/observer/DefaultSessionObserverTest.kt +++ b/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/observer/DefaultSessionObserverTest.kt @@ -51,7 +51,7 @@ import org.junit.Test runCurrent() val listener = TestSessionListener() sut.addListener(listener) - databaseSessionStore.storeData(sessionData.toApiModel()) + databaseSessionStore.addSession(sessionData.toApiModel()) listener.assertEvents(TestSessionListener.Event.Created(sessionData.userId)) sut.removeListener(listener) coroutineContext.cancelChildren() @@ -64,7 +64,7 @@ import org.junit.Test runCurrent() val listener = TestSessionListener() sut.addListener(listener) - databaseSessionStore.storeData(sessionData.toApiModel()) + databaseSessionStore.addSession(sessionData.toApiModel()) listener.assertEvents(TestSessionListener.Event.Created(sessionData.userId)) databaseSessionStore.removeSession(sessionData.userId) listener.assertEvents( diff --git a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt index 8228adada5..0ab12c72fb 100644 --- a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt +++ b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt @@ -37,7 +37,7 @@ class InMemorySessionStore( override fun sessionsFlow(): Flow> = sessionDataListFlow.asStateFlow() - override suspend fun storeData(sessionData: SessionData) { + override suspend fun addSession(sessionData: SessionData) { val currentList = sessionDataListFlow.value.toMutableList() currentList.removeAll { it.userId == sessionData.userId } currentList.add(sessionData) From 80fa442b64ae0d878eb240d0c07d636a862172bd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 5 Sep 2025 15:59:36 +0200 Subject: [PATCH 096/145] Rename API and update test. --- .../libraries/sessionstorage/api/SessionStore.kt | 2 +- .../sessionstorage/impl/DatabaseSessionStore.kt | 2 +- .../sessionstorage/impl/DatabaseSessionStoreTest.kt | 10 ++++++---- .../sessionstorage/test/InMemorySessionStore.kt | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionStore.kt b/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionStore.kt index 74171c7a80..50e9c6f787 100644 --- a/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionStore.kt +++ b/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionStore.kt @@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map interface SessionStore { - fun isLoggedIn(): Flow + fun loggedInStateFlow(): Flow fun sessionsFlow(): Flow> suspend fun addSession(sessionData: SessionData) diff --git a/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStore.kt b/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStore.kt index 72e2a41c57..f74676427d 100644 --- a/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStore.kt +++ b/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStore.kt @@ -33,7 +33,7 @@ class DatabaseSessionStore( ) : SessionStore { private val sessionDataMutex = Mutex() - override fun isLoggedIn(): Flow { + override fun loggedInStateFlow(): Flow { return database.sessionDataQueries.selectFirst() .asFlow() .mapToOneOrNull(dispatchers.io) diff --git a/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTest.kt b/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTest.kt index bac797270d..f05b15a0b7 100644 --- a/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTest.kt +++ b/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTest.kt @@ -54,12 +54,14 @@ class DatabaseSessionStoreTest { } @Test - fun `isLoggedIn emits true while there are sessions in the DB`() = runTest { - databaseSessionStore.isLoggedIn().test { + fun `loggedInStateFlow emits LoggedIn while there are sessions in the DB`() = runTest { + databaseSessionStore.loggedInStateFlow().test { assertThat(awaitItem()).isEqualTo(LoggedInState.NotLoggedIn) - database.sessionDataQueries.insertSessionData(aSessionData) + databaseSessionStore.addSession(aSessionData.toApiModel()) assertThat(awaitItem()).isEqualTo(LoggedInState.LoggedIn(sessionId = aSessionData.userId, isTokenValid = true)) - database.sessionDataQueries.removeSession(aSessionData.userId) + // TODO add more sessions in multi-account PR. + // Remove the first session + databaseSessionStore.removeSession(aSessionData.userId) assertThat(awaitItem()).isEqualTo(LoggedInState.NotLoggedIn) } } diff --git a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt index 0ab12c72fb..eb1645fddf 100644 --- a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt +++ b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt @@ -20,7 +20,7 @@ class InMemorySessionStore( ) : SessionStore { private val sessionDataListFlow = MutableStateFlow(initialList) - override fun isLoggedIn(): Flow { + override fun loggedInStateFlow(): Flow { return sessionDataListFlow.map { if (it.isEmpty()) { LoggedInState.NotLoggedIn From 121eb11fa753328e890e96fa9ce37ef383e48b4d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 5 Sep 2025 16:04:08 +0200 Subject: [PATCH 097/145] Remove MatrixAuthenticationService.loggedInStateFlow() --- .../element/android/appnav/root/RootNavStateFlowFactory.kt | 6 +++--- .../matrix/api/auth/MatrixAuthenticationService.kt | 3 --- .../matrix/impl/auth/RustMatrixAuthenticationService.kt | 6 ------ .../matrix/test/auth/FakeMatrixAuthenticationService.kt | 7 ------- 4 files changed, 3 insertions(+), 19 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/root/RootNavStateFlowFactory.kt b/appnav/src/main/kotlin/io/element/android/appnav/root/RootNavStateFlowFactory.kt index 962bac614b..dfa478d6be 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/root/RootNavStateFlowFactory.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/root/RootNavStateFlowFactory.kt @@ -12,9 +12,9 @@ import com.bumble.appyx.core.state.SavedStateMap import dev.zacsweers.metro.Inject import io.element.android.appnav.di.MatrixSessionCache import io.element.android.features.preferences.api.CacheService -import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder import io.element.android.libraries.preferences.api.store.SessionPreferencesStoreFactory +import io.element.android.libraries.sessionstorage.api.SessionStore import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flow @@ -28,7 +28,7 @@ private const val SAVE_INSTANCE_KEY = "io.element.android.x.RootNavStateFlowFact */ @Inject class RootNavStateFlowFactory( - private val authenticationService: MatrixAuthenticationService, + private val sessionStore: SessionStore, private val cacheService: CacheService, private val matrixSessionCache: MatrixSessionCache, private val imageLoaderHolder: ImageLoaderHolder, @@ -39,7 +39,7 @@ class RootNavStateFlowFactory( fun create(savedStateMap: SavedStateMap?): Flow { return combine( cacheIndexFlow(savedStateMap), - authenticationService.loggedInStateFlow(), + sessionStore.loggedInStateFlow(), ) { cacheIndex, loggedInState -> RootNavState( cacheIndex = cacheIndex, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt index d1c47ae663..51778211cc 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt @@ -13,12 +13,9 @@ import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.core.SessionId -import io.element.android.libraries.sessionstorage.api.LoggedInState -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow interface MatrixAuthenticationService { - fun loggedInStateFlow(): Flow suspend fun getLatestSessionId(): SessionId? /** 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 b3300fb746..c24250f27c 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 @@ -33,11 +33,9 @@ import io.element.android.libraries.matrix.impl.keys.PassphraseGenerator import io.element.android.libraries.matrix.impl.mapper.toSessionData import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory -import io.element.android.libraries.sessionstorage.api.LoggedInState import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionStore import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.withContext @@ -83,10 +81,6 @@ class RustMatrixAuthenticationService( .also { sessionPaths = it } } - override fun loggedInStateFlow(): Flow { - return sessionStore.isLoggedIn() - } - override suspend fun getLatestSessionId(): SessionId? = withContext(coroutineDispatchers.io) { sessionStore.getLatestSession()?.userId?.let { SessionId(it) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt index f236c37da8..79f9942628 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt @@ -19,14 +19,11 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.FakeMatrixClient -import io.element.android.libraries.sessionstorage.api.LoggedInState import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.simulateLongTask -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.flowOf val A_OIDC_DATA = OidcDetails(url = "a-url") @@ -46,10 +43,6 @@ class FakeMatrixAuthenticationService( var getLatestSessionIdLambda: (() -> SessionId?) = { null } - override fun loggedInStateFlow(): Flow { - return flowOf(LoggedInState.NotLoggedIn) - } - override suspend fun getLatestSessionId(): SessionId? = getLatestSessionIdLambda() override suspend fun restoreSession(sessionId: SessionId): Result { From a8c12892a9c22fe6370f8d98a839e849056bbe48 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Sep 2025 15:21:05 +0200 Subject: [PATCH 098/145] Change test in RustMatrixAuthenticationServiceTest --- .../matrix/impl/FakeClientBuilderProvider.kt | 6 ++-- .../impl/RustMatrixClientFactoryTest.kt | 3 +- .../RustMatrixAuthenticationServiceTest.kt | 30 ++++++++++++++----- .../impl/fixtures/fakes/FakeFfiClient.kt | 8 +++++ .../fixtures/fakes/FakeFfiClientBuilder.kt | 8 ++--- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeClientBuilderProvider.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeClientBuilderProvider.kt index 3406b6686a..89e0574fdf 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeClientBuilderProvider.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeClientBuilderProvider.kt @@ -10,8 +10,10 @@ package io.element.android.libraries.matrix.impl import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClientBuilder import org.matrix.rustcomponents.sdk.ClientBuilder -class FakeClientBuilderProvider : ClientBuilderProvider { +class FakeClientBuilderProvider( + private val provideResult: () -> ClientBuilder = { FakeFfiClientBuilder() } +) : ClientBuilderProvider { override fun provide(): ClientBuilder { - return FakeFfiClientBuilder() + return provideResult() } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt index 6b39f7b248..1cb56dcbeb 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt @@ -39,6 +39,7 @@ fun TestScope.createRustMatrixClientFactory( baseDirectory: File = File("/base"), cacheDirectory: File = File("/cache"), sessionStore: SessionStore = InMemorySessionStore(), + clientBuilderProvider: ClientBuilderProvider = FakeClientBuilderProvider(), ) = RustMatrixClientFactory( baseDirectory = baseDirectory, cacheDirectory = cacheDirectory, @@ -52,5 +53,5 @@ fun TestScope.createRustMatrixClientFactory( analyticsService = FakeAnalyticsService(), featureFlagService = FakeFeatureFlagService(), timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), - clientBuilderProvider = FakeClientBuilderProvider(), + clientBuilderProvider = clientBuilderProvider, ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt index 175e1722d9..1cb5db91f6 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt @@ -8,14 +8,17 @@ package io.element.android.libraries.matrix.impl.auth import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.impl.ClientBuilderProvider +import io.element.android.libraries.matrix.impl.FakeClientBuilderProvider import io.element.android.libraries.matrix.impl.createRustMatrixClientFactory +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClientBuilder +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory import io.element.android.libraries.matrix.test.auth.FakeOidcRedirectUrlProvider import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore -import io.element.android.libraries.sessionstorage.test.aSessionData import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest @@ -24,18 +27,28 @@ import java.io.File class RustMatrixAuthenticationServiceTest { @Test - fun `getLatestSessionId should return the value from the store`() = runTest { - val sessionStore = InMemorySessionStore() + fun `setHomeserver is successful`() = runTest { val sut = createRustMatrixAuthenticationService( - sessionStore = sessionStore, + clientBuilderProvider = FakeClientBuilderProvider( + provideResult = { + FakeFfiClientBuilder( + buildResult = { + FakeFfiClient( + homeserverLoginDetailsResult = { + FakeFfiHomeserverLoginDetails() + } + ) + } + ) + } + ), ) - assertThat(sut.getLatestSessionId()).isNull() - sessionStore.storeData(aSessionData(sessionId = "@alice:server.org")) - assertThat(sut.getLatestSessionId()).isEqualTo(SessionId("@alice:server.org")) + assertThat(sut.setHomeserver("matrix.org").isSuccess).isTrue() } private fun TestScope.createRustMatrixAuthenticationService( sessionStore: SessionStore = InMemorySessionStore(), + clientBuilderProvider: ClientBuilderProvider = FakeClientBuilderProvider(), ): RustMatrixAuthenticationService { val baseDirectory = File("/base") val cacheDirectory = File("/cache") @@ -43,6 +56,7 @@ class RustMatrixAuthenticationServiceTest { baseDirectory = baseDirectory, cacheDirectory = cacheDirectory, sessionStore = sessionStore, + clientBuilderProvider = clientBuilderProvider, ) return RustMatrixAuthenticationService( sessionPathsFactory = SessionPathsFactory(baseDirectory, cacheDirectory), diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt index 638e0a2f70..8225ce5ebf 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt @@ -15,6 +15,7 @@ import io.element.android.tests.testutils.simulateLongTask import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.ClientDelegate import org.matrix.rustcomponents.sdk.Encryption +import org.matrix.rustcomponents.sdk.HomeserverLoginDetails import org.matrix.rustcomponents.sdk.IgnoredUsersListener import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.NotificationClient @@ -41,6 +42,7 @@ class FakeFfiClient( private val session: Session = aRustSession(), private val clearCachesResult: () -> Unit = { lambdaError() }, private val withUtdHook: (UnableToDecryptDelegate) -> Unit = { lambdaError() }, + private val homeserverLoginDetailsResult: () -> HomeserverLoginDetails = { lambdaError() }, private val closeResult: () -> Unit = {}, ) : Client(NoPointer) { override fun userId(): String = userId @@ -71,6 +73,7 @@ class FakeFfiClient( override suspend fun ignoredUsers(): List { return emptyList() } + override fun subscribeToIgnoredUsers(listener: IgnoredUsersListener): TaskHandle { return FakeFfiTaskHandle() } @@ -78,5 +81,10 @@ class FakeFfiClient( override suspend fun getProfile(userId: String): UserProfile { return UserProfile(userId = userId, displayName = null, avatarUrl = null) } + + override suspend fun homeserverLoginDetails(): HomeserverLoginDetails { + return homeserverLoginDetailsResult() + } + override fun close() = closeResult() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt index 6e0c73b350..87614304f3 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt @@ -17,7 +17,9 @@ import uniffi.matrix_sdk.BackupDownloadStrategy import uniffi.matrix_sdk_crypto.CollectStrategy import uniffi.matrix_sdk_crypto.DecryptionSettings -class FakeFfiClientBuilder : ClientBuilder(NoPointer) { +class FakeFfiClientBuilder( + val buildResult: () -> Client = { FakeFfiClient(withUtdHook = {}) } +) : ClientBuilder(NoPointer) { override fun addRootCertificates(certificates: List) = this override fun autoEnableBackups(autoEnableBackups: Boolean) = this override fun autoEnableCrossSigning(autoEnableCrossSigning: Boolean) = this @@ -41,7 +43,5 @@ class FakeFfiClientBuilder : ClientBuilder(NoPointer) { override fun enableShareHistoryOnInvite(enableShareHistoryOnInvite: Boolean): ClientBuilder = this override fun threadsEnabled(enabled: Boolean, threadSubscriptions: Boolean): ClientBuilder = this - override suspend fun build(): Client { - return FakeFfiClient(withUtdHook = {}) - } + override suspend fun build() = buildResult() } From 6f827bb09014bc039ba36842db7b393ffbfabb85 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Sep 2025 15:27:20 +0200 Subject: [PATCH 099/145] Do not use MatrixAuthenticationService in RootFlowNode, only use SessionStore --- .../kotlin/io/element/android/appnav/RootFlowNode.kt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 c67496ef87..3f1d40335d 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt @@ -46,13 +46,13 @@ import io.element.android.libraries.architecture.waitForChildAttached import io.element.android.libraries.core.uri.ensureProtocol import io.element.android.libraries.deeplink.api.DeeplinkData import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator -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.oidc.api.OidcAction import io.element.android.libraries.oidc.api.OidcActionFlow import io.element.android.libraries.sessionstorage.api.LoggedInState +import io.element.android.libraries.sessionstorage.api.SessionStore import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -64,7 +64,7 @@ import timber.log.Timber class RootFlowNode( @Assisted val buildContext: BuildContext, @Assisted plugins: List, - private val authenticationService: MatrixAuthenticationService, + private val sessionStore: SessionStore, private val accountProviderAccessControl: AccountProviderAccessControl, private val navStateFlowFactory: RootNavStateFlowFactory, private val matrixSessionCache: MatrixSessionCache, @@ -152,7 +152,7 @@ class RootFlowNode( onSuccess: (SessionId) -> Unit, onFailure: () -> Unit ) { - val latestSessionId = authenticationService.getLatestSessionId() + val latestSessionId = sessionStore.getLatestSessionId() if (latestSessionId == null) { onFailure() return @@ -268,7 +268,7 @@ class RootFlowNode( private suspend fun onLoginLink(params: LoginParams) { // Is there a session already? - val latestSessionId = authenticationService.getLatestSessionId() + val latestSessionId = sessionStore.getLatestSessionId() if (latestSessionId == null) { // No session, open login if (accountProviderAccessControl.isAllowedToConnectToAccountProvider(params.accountProvider.ensureProtocol())) { @@ -285,7 +285,7 @@ class RootFlowNode( private suspend fun onIncomingShare(intent: Intent) { // Is there a session already? - val latestSessionId = authenticationService.getLatestSessionId() + val latestSessionId = sessionStore.getLatestSessionId() if (latestSessionId == null) { // No session, open login switchToNotLoggedInFlow(null) @@ -342,3 +342,5 @@ class RootFlowNode( .attachSession() } } + +private suspend fun SessionStore.getLatestSessionId() = getLatestSession()?.userId?.let(::SessionId) From 92b8be99d13c9b97aa501c9ec4284f8e411ea9b8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Sep 2025 15:31:07 +0200 Subject: [PATCH 100/145] Remove MatrixAuthenticationService.getLatestSessionId() --- .../libraries/matrix/api/auth/MatrixAuthenticationService.kt | 2 -- .../matrix/impl/auth/RustMatrixAuthenticationService.kt | 4 ---- .../matrix/test/auth/FakeMatrixAuthenticationService.kt | 4 ---- 3 files changed, 10 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt index 51778211cc..38777944ee 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt @@ -16,8 +16,6 @@ import io.element.android.libraries.matrix.api.core.SessionId import kotlinx.coroutines.flow.StateFlow interface MatrixAuthenticationService { - suspend fun getLatestSessionId(): SessionId? - /** * Restore a session from a [sessionId]. * Do not restore anything it the access token is not valid anymore. 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 c24250f27c..24201aaf63 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 @@ -81,10 +81,6 @@ class RustMatrixAuthenticationService( .also { sessionPaths = it } } - override suspend fun getLatestSessionId(): SessionId? = withContext(coroutineDispatchers.io) { - sessionStore.getLatestSession()?.userId?.let { SessionId(it) } - } - override suspend fun restoreSession(sessionId: SessionId): Result = withContext(coroutineDispatchers.io) { runCatchingExceptions { val sessionData = sessionStore.getSession(sessionId.value) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt index 79f9942628..f1554df1d0 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt @@ -41,10 +41,6 @@ class FakeMatrixAuthenticationService( private var matrixClient: MatrixClient? = null private var onAuthenticationListener: ((MatrixClient) -> Unit)? = null - var getLatestSessionIdLambda: (() -> SessionId?) = { null } - - override suspend fun getLatestSessionId(): SessionId? = getLatestSessionIdLambda() - override suspend fun restoreSession(sessionId: SessionId): Result { matrixClientResult?.let { return it.invoke(sessionId) From 5c893e7de1e1e0baba5b781bed6b714546554343 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 19 Sep 2025 16:24:06 +0200 Subject: [PATCH 101/145] Add logs to detect duplicates in the room list (#5364) * Add logs to detect duplicates in the room list * Add comments and helper class about the caching results logging --- .../impl/datasource/RoomListDataSource.kt | 34 ++++++++++++++++++- .../impl/roomlist/RoomSummaryListProcessor.kt | 6 ++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt index 28f7f95908..b9e8d27bf7 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt @@ -30,6 +30,7 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext +import timber.log.Timber import kotlin.time.Duration.Companion.seconds @Inject @@ -102,13 +103,44 @@ class RoomListDataSource( } private suspend fun buildAndEmitAllRooms(roomSummaries: List, useCache: Boolean = true) { + // Used to detect duplicates in the room list summaries - see comment below + data class CacheResult(val index: Int, val fromCache: Boolean) + val cachingResults = mutableMapOf>() + val roomListRoomSummaries = diffCache.indices().mapNotNull { index -> if (useCache) { - diffCache.get(index) ?: buildAndCacheItem(roomSummaries, index) + diffCache.get(index)?.let { cachedItem -> + // Add the cached item to the caching results + val pairs = cachingResults.getOrDefault(cachedItem.roomId, mutableListOf()) + pairs.add(CacheResult(index, fromCache = true)) + cachingResults[cachedItem.roomId] = pairs + cachedItem + } ?: run { + roomSummaries.getOrNull(index)?.roomId?.let { + // Add the non-cached item to the caching results + val pairs = cachingResults.getOrDefault(it, mutableListOf()) + pairs.add(CacheResult(index, fromCache = false)) + cachingResults[it] = pairs + } + buildAndCacheItem(roomSummaries, index) + } } else { + roomSummaries.getOrNull(index)?.roomId?.let { + // Add the non-cached item to the caching results + val pairs = cachingResults.getOrDefault(it, mutableListOf()) + pairs.add(CacheResult(index, fromCache = false)) + cachingResults[it] = pairs + } buildAndCacheItem(roomSummaries, index) } } + + // TODO remove once https://github.com/element-hq/element-x-android/issues/5031 has been confirmed as fixed + val duplicates = cachingResults.filter { (_, operations) -> operations.size > 1 } + if (duplicates.isNotEmpty()) { + Timber.e("Found duplicates in room summaries after an UI update: $duplicates. This could be a race condition/caching issue of some kind") + } + _allRooms.emit(roomListRoomSummaries.toImmutableList()) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt index 66931a1f13..e26cea1c94 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt @@ -33,6 +33,12 @@ class RoomSummaryListProcessor( updates.forEach { update -> applyUpdate(update) } + + // TODO remove once https://github.com/element-hq/element-x-android/issues/5031 has been confirmed as fixed + val duplicates = groupingBy { it.roomId }.eachCount().filter { it.value > 1 } + if (duplicates.isNotEmpty()) { + Timber.e("Found duplicates in room summaries after a list update from the SDK: $duplicates. Updates: $updates") + } } } From e52f2e22744323b23e7e6ed374df6b8fd0cbe789 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 19 Sep 2025 16:23:34 +0200 Subject: [PATCH 102/145] fix (room navigation) : fix navigation when leaving room/space from another device --- .../android/appnav/room/RoomFlowNode.kt | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt index f2df6ee8c9..6f04a08f7b 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt @@ -54,7 +54,6 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.shareIn @@ -111,7 +110,7 @@ class RoomFlowNode( data class JoinedRoom(val roomId: RoomId) : NavTarget @Parcelize - data class Space(val spaceId: RoomId) : NavTarget + data class JoinedSpace(val spaceId: RoomId) : NavTarget } override fun onBuilt() { @@ -149,30 +148,28 @@ class RoomFlowNode( .withPreviousValue() combine(currentMembershipFlow, isSpaceFlow) { (previousMembership, membership), isSpace -> Timber.d("Room membership: $membership") - when (membership) { - CurrentUserMembership.JOINED -> { - if (isSpace) { - backstack.newRoot(NavTarget.Space(spaceId = roomId)) - } else { - backstack.newRoot(NavTarget.JoinedRoom(roomId)) - } + if (membership == CurrentUserMembership.JOINED) { + if (isSpace) { + backstack.newRoot(NavTarget.JoinedSpace(spaceId = roomId)) + } else { + backstack.newRoot(NavTarget.JoinedRoom(roomId)) } - else -> { - if (membership == CurrentUserMembership.LEFT && previousMembership == CurrentUserMembership.JOINED) { - // The user left the room in this device, remove the room from the backstack - if (!membershipUpdateFlow.first().isUserInRoom) { - navigateUp() - } - } else { - // Was invited or the room is not known, display the join room screen - backstack.newRoot( - NavTarget.JoinRoom( - roomId = roomId, - serverNames = serverNames, - trigger = inputs.trigger.getOrNull() ?: JoinedRoom.Trigger.Invite, - ) + } else { + val leavingFromCurrentDevice = + membership == CurrentUserMembership.LEFT && + previousMembership == CurrentUserMembership.JOINED && + membershipUpdateFlow.replayCache.lastOrNull()?.isUserInRoom == false + + if (leavingFromCurrentDevice) { + navigateUp() + } else { + backstack.newRoot( + NavTarget.JoinRoom( + roomId = roomId, + serverNames = serverNames, + trigger = inputs.trigger.getOrNull() ?: JoinedRoom.Trigger.Invite, ) - } + ) } } }.launchIn(lifecycleScope) @@ -214,7 +211,7 @@ class RoomFlowNode( ) createNode(buildContext, plugins = listOf(inputs) + roomFlowNodeCallback) } - is NavTarget.Space -> { + is NavTarget.JoinedSpace -> { val spaceCallback = plugins().single() spaceEntryPoint.nodeBuilder(this, buildContext) .inputs(SpaceEntryPoint.Inputs(roomId = navTarget.spaceId)) From 80810cddf12acd421593ff007202ca27b1ea68ac Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 19 Sep 2025 16:59:46 +0200 Subject: [PATCH 103/145] Rename val --- .../io/element/android/features/ftue/impl/FtueFlowNode.kt | 6 +++--- .../android/features/ftue/impl/DefaultFtueEntryPointTest.kt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt index 1f4ca9e4ee..51414c70fd 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt @@ -49,7 +49,7 @@ import kotlinx.parcelize.Parcelize class FtueFlowNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val ftueState: DefaultFtueService, + private val defaultFtueService: DefaultFtueService, private val analyticsEntryPoint: AnalyticsEntryPoint, private val analyticsService: AnalyticsService, private val lockScreenEntryPoint: LockScreenEntryPoint, @@ -90,7 +90,7 @@ class FtueFlowNode( .onEach { moveToNextStepIfNeeded() } .launchIn(lifecycleScope) - ftueState.isVerificationStatusKnown + defaultFtueService.isVerificationStatusKnown .filter { it } .onEach { moveToNextStepIfNeeded() } .launchIn(lifecycleScope) @@ -134,7 +134,7 @@ class FtueFlowNode( } private fun moveToNextStepIfNeeded() = lifecycleScope.launch { - when (ftueState.getNextStep()) { + when (defaultFtueService.getNextStep()) { FtueStep.WaitingForInitialState -> { backstack.newRoot(NavTarget.Placeholder) } diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt index 50cc2eadce..2f832e3925 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt @@ -36,7 +36,7 @@ class DefaultFtueEntryPointTest { buildContext = buildContext, plugins = plugins, analyticsEntryPoint = { _, _ -> lambdaError() }, - ftueState = createDefaultFtueService(), + defaultFtueService = createDefaultFtueService(), analyticsService = FakeAnalyticsService(), lockScreenEntryPoint = object : LockScreenEntryPoint { override fun nodeBuilder( From 91455c6019620f2996dd12d56164367fb5c84658 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 19 Sep 2025 17:42:47 +0200 Subject: [PATCH 104/145] feature (space) : add string "No space name" --- .../android/features/space/impl/SpaceView.kt | 2 +- .../matrix/ui/components/SpaceHeaderView.kt | 16 ++++++++++++---- .../matrix/ui/components/SpaceRoomItemView.kt | 4 +++- .../ui-strings/src/main/res/values/localazy.xml | 1 + 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt index f3bdf7379b..53aa61a0c7 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceView.kt @@ -183,7 +183,7 @@ private fun SpaceAvatarAndNameRow( .semantics { heading() }, - text = name ?: stringResource(CommonStrings.common_no_room_name), + text = name ?: stringResource(CommonStrings.common_no_space_name), style = ElementTheme.typography.fontBodyLgMedium, fontStyle = FontStyle.Italic.takeIf { name == null }, maxLines = 1, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt index ecfde229c9..6dbe7ebf72 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt @@ -10,6 +10,8 @@ package io.element.android.libraries.matrix.ui.components import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.tooling.preview.datasource.LoremIpsum import androidx.compose.ui.unit.dp import io.element.android.libraries.designsystem.atomic.atoms.RoomPreviewDescriptionAtom @@ -24,6 +26,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -51,8 +54,13 @@ fun SpaceHeaderView( ) }, title = { - name?.let { + if (name != null) { RoomPreviewTitleAtom(title = name) + } else { + RoomPreviewTitleAtom( + title = stringResource(id = CommonStrings.common_no_space_name), + fontStyle = FontStyle.Italic + ) } }, subtitle = { @@ -63,10 +71,10 @@ fun SpaceHeaderView( ) } }, - description = if (topic != null) { - { RoomPreviewDescriptionAtom(description = topic, maxLines = topicMaxLines) } - } else { + description = if (topic.isNullOrBlank()) { null + } else { + { RoomPreviewDescriptionAtom(description = topic, maxLines = topicMaxLines) } }, memberCount = { SpaceMembersView( diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt index be540d486d..23baf476c0 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt @@ -69,6 +69,7 @@ fun SpaceRoomItemView( onLongClick = onLongClick, ) { NameAndIndicatorRow( + isSpace = spaceRoom.isSpace, name = spaceRoom.name, showIndicator = showUnreadIndicator ) @@ -130,6 +131,7 @@ private fun SubtitleRow( @Composable private fun NameAndIndicatorRow( + isSpace: Boolean, name: String?, showIndicator: Boolean, modifier: Modifier = Modifier, @@ -142,7 +144,7 @@ private fun NameAndIndicatorRow( Text( modifier = Modifier.weight(1f), style = ElementTheme.typography.fontBodyLgMedium, - text = name ?: stringResource(id = CommonStrings.common_no_room_name), + text = name ?: stringResource(id = if(isSpace) CommonStrings.common_no_space_name else CommonStrings.common_no_room_name), fontStyle = FontStyle.Italic.takeIf { name == null }, color = ElementTheme.colors.textPrimary, maxLines = 1, diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 78d3ca5fdc..32077e22e7 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -246,6 +246,7 @@ Reason: %1$s." "%1$s (%2$s)" "No results" "No room name" + "No space name" "Not encrypted" "Offline" "Open source licenses" From 0bdf998c7f8cebe29de6b2bef9241253e1d6e564 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 15:53:02 +0000 Subject: [PATCH 105/145] Update dependency org.matrix.rustcomponents:sdk-android to v25.9.19 (#5377) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- .../libraries/matrix/impl/fixtures/factories/SpaceRoom.kt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index eca610ae30..525572f9e2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -166,7 +166,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.18" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.19" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt index 01c5deca68..b9f665add1 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt @@ -17,6 +17,7 @@ import org.matrix.rustcomponents.sdk.SpaceRoom fun aRustSpaceRoom( roomId: RoomId = A_ROOM_ID, + isDirect: Boolean = false, canonicalAlias: String? = null, name: String? = null, topic: String? = null, @@ -31,6 +32,7 @@ fun aRustSpaceRoom( heroes: List = emptyList(), ) = SpaceRoom( roomId = roomId.value, + isDirect = isDirect, canonicalAlias = canonicalAlias, name = name, topic = topic, From f9d8c9a065a55c139abd51f931441f726f57a782 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 19 Sep 2025 17:21:00 +0200 Subject: [PATCH 106/145] Ensure we wait for user confirmation of session verified before going to next step. --- .../features/ftue/impl/FtueFlowNode.kt | 37 +++----- .../ftue/impl/state/DefaultFtueService.kt | 62 ++++++++----- .../ftue/impl/state/InternalFtueState.kt | 18 ++++ .../ftue/impl/DefaultFtueEntryPointTest.kt | 2 - .../ftue/impl/DefaultFtueServiceTest.kt | 90 ++++++++++--------- 5 files changed, 119 insertions(+), 90 deletions(-) create mode 100644 features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/InternalFtueState.kt diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt index 51414c70fd..a4aa9f18d7 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt @@ -14,7 +14,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.lifecycle.lifecycleScope -import com.bumble.appyx.core.lifecycle.subscribe import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin @@ -30,18 +29,16 @@ import io.element.android.features.ftue.impl.notifications.NotificationsOptInNod import io.element.android.features.ftue.impl.sessionverification.FtueSessionVerificationFlowNode import io.element.android.features.ftue.impl.state.DefaultFtueService import io.element.android.features.ftue.impl.state.FtueStep +import io.element.android.features.ftue.impl.state.InternalFtueState import io.element.android.features.lockscreen.api.LockScreenEntryPoint 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.theme.components.CircularProgressIndicator import io.element.android.libraries.di.SessionScope -import io.element.android.services.analytics.api.AnalyticsService -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize @ContributesNode(SessionScope::class) @@ -51,7 +48,6 @@ class FtueFlowNode( @Assisted plugins: List, private val defaultFtueService: DefaultFtueService, private val analyticsEntryPoint: AnalyticsEntryPoint, - private val analyticsService: AnalyticsService, private val lockScreenEntryPoint: LockScreenEntryPoint, ) : BaseFlowNode( backstack = BackStack( @@ -80,19 +76,11 @@ class FtueFlowNode( override fun onBuilt() { super.onBuilt() - - lifecycle.subscribe(onCreate = { - moveToNextStepIfNeeded() - }) - - analyticsService.didAskUserConsentFlow - .distinctUntilChanged() - .onEach { moveToNextStepIfNeeded() } - .launchIn(lifecycleScope) - - defaultFtueService.isVerificationStatusKnown - .filter { it } - .onEach { moveToNextStepIfNeeded() } + defaultFtueService.ftueStepStateFlow + .filterIsInstance(InternalFtueState.Incomplete::class) + .onEach { + showStep(it.nextStep) + } .launchIn(lifecycleScope) } @@ -104,7 +92,7 @@ class FtueFlowNode( is NavTarget.SessionVerification -> { val callback = object : FtueSessionVerificationFlowNode.Callback { override fun onDone() { - moveToNextStepIfNeeded() + defaultFtueService.onUserCompletedSessionVerification() } } createNode(buildContext, listOf(callback)) @@ -112,7 +100,7 @@ class FtueFlowNode( NavTarget.NotificationsOptIn -> { val callback = object : NotificationsOptInNode.Callback { override fun onNotificationsOptInFinished() { - moveToNextStepIfNeeded() + defaultFtueService.updateFtueStep() } } createNode(buildContext, listOf(callback)) @@ -123,7 +111,7 @@ class FtueFlowNode( NavTarget.LockScreenSetup -> { val callback = object : LockScreenEntryPoint.Callback { override fun onSetupDone() { - moveToNextStepIfNeeded() + defaultFtueService.updateFtueStep() } } lockScreenEntryPoint.nodeBuilder(this, buildContext, LockScreenEntryPoint.Target.Setup) @@ -133,8 +121,8 @@ class FtueFlowNode( } } - private fun moveToNextStepIfNeeded() = lifecycleScope.launch { - when (defaultFtueService.getNextStep()) { + private fun showStep(ftueStep: FtueStep) { + when (ftueStep) { FtueStep.WaitingForInitialState -> { backstack.newRoot(NavTarget.Placeholder) } @@ -150,7 +138,6 @@ class FtueFlowNode( FtueStep.LockscreenSetup -> { backstack.newRoot(NavTarget.LockScreenSetup) } - null -> Unit } } 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 43e85aa708..28a1ab25d9 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 @@ -9,13 +9,13 @@ package io.element.android.features.ftue.impl.state import android.Manifest import android.os.Build -import androidx.annotation.VisibleForTesting import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Inject import dev.zacsweers.metro.SingleIn import io.element.android.features.ftue.api.state.FtueService import io.element.android.features.ftue.api.state.FtueState import io.element.android.features.lockscreen.api.LockScreenService +import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.matrix.api.verification.SessionVerificationService @@ -26,26 +26,39 @@ import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch @ContributesBinding(SessionScope::class) @SingleIn(SessionScope::class) @Inject class DefaultFtueService( private val sdkVersionProvider: BuildVersionSdkIntProvider, - @SessionCoroutineScope sessionCoroutineScope: CoroutineScope, + @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val analyticsService: AnalyticsService, private val permissionStateProvider: PermissionStateProvider, private val lockScreenService: LockScreenService, private val sessionVerificationService: SessionVerificationService, private val sessionPreferencesStore: SessionPreferencesStore, ) : FtueService { - override val state = MutableStateFlow(FtueState.Unknown) + private val userNeedsToConfirmSessionVerificationSuccess = MutableStateFlow(false) + + val ftueStepStateFlow = MutableStateFlow(InternalFtueState.Unknown) + + override val state = ftueStepStateFlow + .mapState { + when (it) { + is InternalFtueState.Unknown -> FtueState.Unknown + is InternalFtueState.Incomplete -> FtueState.Incomplete + is InternalFtueState.Complete -> FtueState.Complete + } + } /** * This flow emits true when the FTUE flow is ready to be displayed. @@ -63,24 +76,37 @@ class DefaultFtueService( } init { - sessionVerificationService.sessionVerifiedStatus - .onEach { updateState() } - .launchIn(sessionCoroutineScope) - - analyticsService.didAskUserConsentFlow - .distinctUntilChanged() - .onEach { updateState() } + combine( + sessionVerificationService.sessionVerifiedStatus.onEach { sessionVerifiedStatus -> + if (sessionVerifiedStatus == SessionVerifiedStatus.NotVerified) { + // Ensure we wait for the user to confirm the session verified screen before going further + userNeedsToConfirmSessionVerificationSuccess.value = true + } + }, + userNeedsToConfirmSessionVerificationSuccess, + analyticsService.didAskUserConsentFlow.distinctUntilChanged(), + ) { + updateFtueStep() + } .launchIn(sessionCoroutineScope) } - suspend fun getNextStep(currentStep: FtueStep? = null): FtueStep? = - when (currentStep) { + fun updateFtueStep() = sessionCoroutineScope.launch { + val step = getNextStep(null) + ftueStepStateFlow.value = when (step) { + null -> InternalFtueState.Complete + else -> InternalFtueState.Incomplete(step) + } + } + + private suspend fun getNextStep(completedStep: FtueStep? = null): FtueStep? = + when (completedStep) { null -> if (!isSessionVerificationStateReady()) { FtueStep.WaitingForInitialState } else { getNextStep(FtueStep.WaitingForInitialState) } - FtueStep.WaitingForInitialState -> if (isSessionNotVerified()) { + FtueStep.WaitingForInitialState -> if (isSessionNotVerified() || userNeedsToConfirmSessionVerificationSuccess.value) { FtueStep.SessionVerification } else { getNextStep(FtueStep.SessionVerification) @@ -137,14 +163,8 @@ class DefaultFtueService( return lockScreenService.isSetupRequired().first() } - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - internal suspend fun updateState() { - val nextStep = getNextStep() - state.value = when { - // Final state, there aren't any more next steps - nextStep == null -> FtueState.Complete - else -> FtueState.Incomplete - } + fun onUserCompletedSessionVerification() { + userNeedsToConfirmSessionVerificationSuccess.value = false } } diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/InternalFtueState.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/InternalFtueState.kt new file mode 100644 index 0000000000..c620a2ca5b --- /dev/null +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/InternalFtueState.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.ftue.impl.state + +sealed interface InternalFtueState { + data object Unknown : InternalFtueState + + data class Incomplete( + val nextStep: FtueStep, + ) : InternalFtueState + + data object Complete : InternalFtueState +} diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt index 2f832e3925..3a8ed11ea2 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt @@ -14,7 +14,6 @@ import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat import io.element.android.features.lockscreen.api.LockScreenEntryPoint -import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest @@ -37,7 +36,6 @@ class DefaultFtueEntryPointTest { plugins = plugins, analyticsEntryPoint = { _, _ -> lambdaError() }, defaultFtueService = createDefaultFtueService(), - analyticsService = FakeAnalyticsService(), lockScreenEntryPoint = object : LockScreenEntryPoint { override fun nodeBuilder( parentNode: com.bumble.appyx.core.node.Node, diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt index 1a4a8738dc..4ec2558c74 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt @@ -13,6 +13,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.ftue.api.state.FtueState import io.element.android.features.ftue.impl.state.DefaultFtueService import io.element.android.features.ftue.impl.state.FtueStep +import io.element.android.features.ftue.impl.state.InternalFtueState import io.element.android.features.lockscreen.api.LockScreenService import io.element.android.features.lockscreen.test.FakeLockScreenService import io.element.android.libraries.matrix.api.verification.SessionVerificationService @@ -69,9 +70,11 @@ class DefaultFtueServiceTest { analyticsService.setDidAskUserConsent() permissionStateProvider.setPermissionGranted() lockScreenService.setIsPinSetup(true) - service.updateState() - - assertThat(service.state.value).isEqualTo(FtueState.Complete) + service.updateFtueStep() + service.state.test { + assertThat(awaitItem()).isEqualTo(FtueState.Unknown) + assertThat(awaitItem()).isEqualTo(FtueState.Complete) + } } @Test @@ -90,9 +93,11 @@ class DefaultFtueServiceTest { sessionVerificationService.emitVerifiedStatus(SessionVerifiedStatus.Verified) permissionStateProvider.setPermissionGranted() lockScreenService.setIsPinSetup(true) - service.updateState() - - assertThat(service.state.value).isEqualTo(FtueState.Complete) + service.updateFtueStep() + service.state.test { + assertThat(awaitItem()).isEqualTo(FtueState.Unknown) + assertThat(awaitItem()).isEqualTo(FtueState.Complete) + } } @Test @@ -109,35 +114,30 @@ class DefaultFtueServiceTest { permissionStateProvider = permissionStateProvider, lockScreenService = lockScreenService, ) - val steps = mutableListOf() - // Session verification - steps.add(service.getNextStep(steps.lastOrNull())) - sessionVerificationService.emitVerifiedStatus(SessionVerifiedStatus.NotVerified) - - // Notifications opt in - steps.add(service.getNextStep(steps.lastOrNull())) - permissionStateProvider.setPermissionGranted() - - // Entering PIN code - steps.add(service.getNextStep(steps.lastOrNull())) - lockScreenService.setIsPinSetup(true) - - // Analytics opt in - steps.add(service.getNextStep(steps.lastOrNull())) - analyticsService.setDidAskUserConsent() - - // Final step (null) - steps.add(service.getNextStep(steps.lastOrNull())) - - assertThat(steps).containsExactly( - FtueStep.SessionVerification, - FtueStep.NotificationsOptIn, - FtueStep.LockscreenSetup, - FtueStep.AnalyticsOptIn, - // Final state - null, - ) + service.ftueStepStateFlow.test { + assertThat(awaitItem()).isEqualTo(InternalFtueState.Unknown) + // Session verification + assertThat(awaitItem()).isEqualTo(InternalFtueState.Incomplete(FtueStep.SessionVerification)) + sessionVerificationService.emitVerifiedStatus(SessionVerifiedStatus.Verified) + // User completes verification + service.onUserCompletedSessionVerification() + // Notifications opt in + assertThat(awaitItem()).isEqualTo(InternalFtueState.Incomplete(FtueStep.NotificationsOptIn)) + permissionStateProvider.setPermissionGranted() + // Simulate event from NotificationsOptInNode.Callback.onNotificationsOptInFinished + service.updateFtueStep() + // Entering PIN code + assertThat(awaitItem()).isEqualTo(InternalFtueState.Incomplete(FtueStep.LockscreenSetup)) + lockScreenService.setIsPinSetup(true) + // Simulate event from LockScreenEntryPoint.Callback.onSetupDone() + service.updateFtueStep() + // Analytics opt in + assertThat(awaitItem()).isEqualTo(InternalFtueState.Incomplete(FtueStep.AnalyticsOptIn)) + analyticsService.setDidAskUserConsent() + // Final step + assertThat(awaitItem()).isEqualTo(InternalFtueState.Complete) + } } @Test @@ -158,10 +158,13 @@ class DefaultFtueServiceTest { permissionStateProvider.setPermissionGranted() lockScreenService.setIsPinSetup(true) - assertThat(service.getNextStep()).isEqualTo(FtueStep.AnalyticsOptIn) - - analyticsService.setDidAskUserConsent() - assertThat(service.getNextStep(null)).isNull() + service.ftueStepStateFlow.test { + assertThat(awaitItem()).isEqualTo(InternalFtueState.Unknown) + // Analytics opt in + assertThat(awaitItem()).isEqualTo(InternalFtueState.Incomplete(FtueStep.AnalyticsOptIn)) + analyticsService.setDidAskUserConsent() + assertThat(awaitItem()).isEqualTo(InternalFtueState.Complete) + } } @Test @@ -180,10 +183,13 @@ class DefaultFtueServiceTest { sessionVerificationService.emitVerifiedStatus(SessionVerifiedStatus.Verified) lockScreenService.setIsPinSetup(true) - assertThat(service.getNextStep()).isEqualTo(FtueStep.AnalyticsOptIn) - - analyticsService.setDidAskUserConsent() - assertThat(service.getNextStep(null)).isNull() + service.ftueStepStateFlow.test { + assertThat(awaitItem()).isEqualTo(InternalFtueState.Unknown) + // Analytics opt in + assertThat(awaitItem()).isEqualTo(InternalFtueState.Incomplete(FtueStep.AnalyticsOptIn)) + analyticsService.setDidAskUserConsent() + assertThat(awaitItem()).isEqualTo(InternalFtueState.Complete) + } } @Test From d525e973d4ae2e6b4dfdb7219e0969622598beeb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 12:41:47 +0000 Subject: [PATCH 107/145] Update dependency org.maplibre.gl:android-sdk to v11.13.5 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cfa6f1f7ff..7f5ad4ff8a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -196,7 +196,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.13.1" +maplibre = "org.maplibre.gl:android-sdk:11.13.5" maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.2" maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" opusencoder = "io.element.android:opusencoder:1.2.0" From 182f8045488c031d5df8f344f2f3cbd862b6a1ca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 16:46:19 +0000 Subject: [PATCH 108/145] Update plugin dependencycheck to v12.1.5 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cfa6f1f7ff..8279a3cc8a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -241,7 +241,7 @@ metro = { id = "dev.zacsweers.metro", version.ref = "metro" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } ktlint = "org.jlleitschuh.gradle.ktlint:13.1.0" dependencygraph = "com.savvasdalkitsis.module-dependency-graph:0.12" -dependencycheck = "org.owasp.dependencycheck:12.1.3" +dependencycheck = "org.owasp.dependencycheck:12.1.5" dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyAnalysis" } paparazzi = "app.cash.paparazzi:2.0.0-alpha02" sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } From eef40f342d33975beb3d0f1880a58a9ea6a9ba24 Mon Sep 17 00:00:00 2001 From: sim Date: Mon, 22 Sep 2025 09:01:41 +0200 Subject: [PATCH 109/145] Put developer settings at the end of the view It used to be before "Sign out" which once the developer setting was enabled went over the build version. So clicking 8 times on the build version instead of 7 to enable dev settings was signing out the user. --- .../features/preferences/impl/root/PreferencesRootView.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt index 85c180ddac..544b5f5b3e 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt @@ -214,9 +214,6 @@ private fun ColumnScope.GeneralSection( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Settings())), onClick = onOpenAdvancedSettings, ) - if (state.showDeveloperSettings) { - DeveloperPreferencesView(onOpenDeveloperSettings) - } ListItem( headlineContent = { Text(stringResource(id = CommonStrings.action_signout)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.SignOut())), @@ -231,6 +228,10 @@ private fun ColumnScope.GeneralSection( onClick = onDeactivateClick, ) } + // Put developer settings at the end, so nothing bad happens if the user clicks 8 times to enable the entry + if (state.showDeveloperSettings) { + DeveloperPreferencesView(onOpenDeveloperSettings) + } } @Composable From 2a3cc2f7592b353c37d6ea0c0be5581d0a37db46 Mon Sep 17 00:00:00 2001 From: sim Date: Mon, 22 Sep 2025 09:13:07 +0200 Subject: [PATCH 110/145] Changed default branch to please the bot From dcec9581cde42c1a50c97125b40cab1341e5d30a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Sep 2025 09:34:32 +0200 Subject: [PATCH 111/145] Simplify the code again. We do not need `isVerificationStatusKnown`. If `sessionVerificationService.sessionVerifiedStatus` is `Unknown`, `isSessionVerificationStateReady()` will return true and `isSessionNotVerified()` will not be called, since the `ftueState` will be `FtueStep.WaitingForInitialState`. Note that TU is still OK with this change. --- .../features/ftue/impl/state/DefaultFtueService.kt | 13 ------------- 1 file changed, 13 deletions(-) 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 28a1ab25d9..ae26ee28bc 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 @@ -28,10 +28,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -60,14 +58,6 @@ class DefaultFtueService( } } - /** - * This flow emits true when the FTUE flow is ready to be displayed. - * In this case, the FTUE flow is ready when the session verification status is known. - */ - val isVerificationStatusKnown = sessionVerificationService.sessionVerifiedStatus - .map { it != SessionVerifiedStatus.Unknown } - .distinctUntilChanged() - override suspend fun reset() { analyticsService.reset() if (sdkVersionProvider.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { @@ -134,9 +124,6 @@ class DefaultFtueService( } private suspend fun isSessionNotVerified(): Boolean { - // Wait until the session verification status is known - isVerificationStatusKnown.filter { it }.first() - return sessionVerificationService.sessionVerifiedStatus.value == SessionVerifiedStatus.NotVerified && !canSkipVerification() } From 30e91e71b0aa45a80f034fb055e0e6266585e067 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 22 Sep 2025 09:56:36 +0200 Subject: [PATCH 112/145] Add room info to the thread's top app bar (#5374) * Add room info to the thread's top app bar * Update screenshots * Fix lint issues --------- Co-authored-by: ElementBot --- .../features/messages/impl/MessagesView.kt | 105 +++++++++++++++++- ...s.messages.impl_MessagesView_Day_15_en.png | 4 +- ...messages.impl_MessagesView_Night_15_en.png | 4 +- ...es.messages.impl_ThreadTopBar_Day_0_en.png | 3 + ....messages.impl_ThreadTopBar_Night_0_en.png | 3 + 5 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Night_0_en.png 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 6a436adabc..1cc84eee78 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 @@ -87,6 +87,7 @@ import io.element.android.libraries.designsystem.components.ExpandableBottomShee import io.element.android.libraries.designsystem.components.ExpandableBottomSheetLayoutState import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog @@ -95,6 +96,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.toAnnotatedString import io.element.android.libraries.designsystem.theme.components.BottomSheetDragHandle +import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text @@ -111,10 +113,14 @@ import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.ui.components.aMatrixUserList +import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.textcomposer.model.TextEditorState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.wysiwyg.link.Link import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList import timber.log.Timber import kotlin.time.Duration.Companion.milliseconds @@ -202,7 +208,13 @@ fun MessagesView( Column { ConnectivityIndicatorView(isOnline = state.hasNetworkConnection) if (state.timelineState.timelineMode is Timeline.Mode.Thread) { - ThreadTopBar(onBackClick = onBackClick) + ThreadTopBar( + roomName = state.roomName, + roomAvatarData = state.roomAvatar, + heroes = state.heroes, + isTombstoned = state.isTombstoned, + onBackClick = onBackClick, + ) } else { MessagesViewTopBar( roomName = state.roomName, @@ -573,14 +585,48 @@ private fun MessagesViewTopBar( @OptIn(ExperimentalMaterial3Api::class) @Composable private fun ThreadTopBar( + roomName: String?, + roomAvatarData: AvatarData, + heroes: ImmutableList, + isTombstoned: Boolean, onBackClick: () -> Unit, + modifier: Modifier = Modifier, ) { TopAppBar( + modifier = modifier, navigationIcon = { BackButton(onClick = onBackClick) }, title = { - Text(stringResource(CommonStrings.common_thread)) + Row(verticalAlignment = Alignment.CenterVertically) { + Avatar( + avatarData = roomAvatarData, + avatarType = AvatarType.Room( + heroes = heroes, + isTombstoned = isTombstoned, + ), + ) + Column( + modifier = Modifier.fillMaxWidth() + .padding(horizontal = 8.dp) + .semantics { + heading() + }, + ) { + Text( + text = stringResource(CommonStrings.common_thread), + style = ElementTheme.typography.fontBodyLgMedium, + ) + Text( + text = roomName ?: stringResource(CommonStrings.common_no_room_name), + style = ElementTheme.typography.fontBodySmRegular, + fontStyle = FontStyle.Italic.takeIf { roomName == null }, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } } ) } @@ -673,3 +719,58 @@ internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class) knockRequestsBannerView = {}, ) } + +@PreviewsDayNight +@Composable +internal fun ThreadTopBarPreview() { + ElementPreview { + val name = "Room name" + val initialsAvatarData = AvatarData( + id = "id", + name = name, + url = null, + size = AvatarSize.TimelineRoom, + ) + Column { + ThreadTopBar( + roomName = name, + roomAvatarData = initialsAvatarData, + heroes = persistentListOf(), + isTombstoned = false, + onBackClick = {}, + ) + HorizontalDivider() + ThreadTopBar( + roomName = name, + roomAvatarData = initialsAvatarData, + heroes = aMatrixUserList().map { it.getAvatarData(AvatarSize.TimelineRoom) }.toImmutableList(), + isTombstoned = false, + onBackClick = {}, + ) + HorizontalDivider() + ThreadTopBar( + roomName = null, + roomAvatarData = initialsAvatarData, + heroes = persistentListOf(), + isTombstoned = false, + onBackClick = {}, + ) + HorizontalDivider() + ThreadTopBar( + roomName = name, + roomAvatarData = initialsAvatarData.copy(url = "https://some-avatar.jpg"), + heroes = persistentListOf(), + isTombstoned = false, + onBackClick = {}, + ) + HorizontalDivider() + ThreadTopBar( + roomName = name, + roomAvatarData = initialsAvatarData, + heroes = persistentListOf(), + isTombstoned = true, + onBackClick = {}, + ) + } + } +} diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_15_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_15_en.png index ff317ac8ad..11b3313094 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:045e0d9605be905e4bbc5d88fc5cfa3bd4a109164709ce5276dedc3dbcf2da80 -size 51119 +oid sha256:9571176fb73b9871b6db3c30679a46c776badb56d4e1919ea882b391d893b8c4 +size 53144 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_15_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_15_en.png index 7fb660b0fb..7d33111f68 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fdb2ca59f48d38d8fa7ebeb9d5768b44f216266a27f6cec9d518b729ecece253 -size 50253 +oid sha256:d6ea6d7eb98c546dbee109d160e2adbbbd4d22d4844835667bfbab1de2060115 +size 52351 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Day_0_en.png new file mode 100644 index 0000000000..29d2a7fee4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:10ef1d5b008da94cdf48525d98bdb1e10f6013124c499f67c9fcd39bee85b7aa +size 33773 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Night_0_en.png new file mode 100644 index 0000000000..6a5b231305 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d98bfa7c506d089ae16b2f35ffa4e189ae1a31ca114333d755fd837b13128759 +size 32921 From 290298ce0155777c5e4a2bd13580a3e2b1d178cd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Sep 2025 10:30:04 +0200 Subject: [PATCH 113/145] Change in clear cache behavior: - Do not reset the analytics store, so that we do not ask the user consent again => Parity with iOS. - Do not reset the permission store, because it contains information that's related to the system permission, which cannot be retrieved otherwise => Should help with #3195. --- .../features/ftue/api/state/FtueService.kt | 3 -- .../ftue/impl/state/DefaultFtueService.kt | 7 --- .../ftue/impl/DefaultFtueServiceTest.kt | 43 ------------------- .../features/ftue/test/FakeFtueService.kt | 9 +--- features/preferences/impl/build.gradle.kts | 2 - .../impl/tasks/ClearCacheUseCase.kt | 3 -- .../tasks/DefaultClearCacheUseCaseTest.kt | 7 --- .../api/PermissionStateProvider.kt | 2 - .../impl/DefaultPermissionStateProvider.kt | 2 - .../test/FakePermissionStateProvider.kt | 7 --- .../analytics/api/AnalyticsService.kt | 5 --- .../analytics/impl/DefaultAnalyticsService.kt | 4 -- .../impl/DefaultAnalyticsServiceTest.kt | 14 ------ .../analytics/noop/NoopAnalyticsService.kt | 1 - .../analytics/test/FakeAnalyticsService.kt | 6 --- 15 files changed, 1 insertion(+), 114 deletions(-) diff --git a/features/ftue/api/src/main/kotlin/io/element/android/features/ftue/api/state/FtueService.kt b/features/ftue/api/src/main/kotlin/io/element/android/features/ftue/api/state/FtueService.kt index 7ea26c548f..b596f328d5 100644 --- a/features/ftue/api/src/main/kotlin/io/element/android/features/ftue/api/state/FtueService.kt +++ b/features/ftue/api/src/main/kotlin/io/element/android/features/ftue/api/state/FtueService.kt @@ -15,9 +15,6 @@ import kotlinx.coroutines.flow.StateFlow interface FtueService { /** The current state of the FTUE. */ val state: StateFlow - - /** Reset the FTUE state. */ - suspend fun reset() } /** The state of the FTUE. */ 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 ae26ee28bc..40f19b1e7a 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 @@ -58,13 +58,6 @@ class DefaultFtueService( } } - override suspend fun reset() { - analyticsService.reset() - if (sdkVersionProvider.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { - permissionStateProvider.resetPermission(Manifest.permission.POST_NOTIFICATIONS) - } - } - init { combine( sessionVerificationService.sessionVerifiedStatus.onEach { sessionVerifiedStatus -> diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt index 4ec2558c74..e46f43f3c3 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt @@ -27,8 +27,6 @@ import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.noop.NoopAnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider -import io.element.android.tests.testutils.lambda.lambdaRecorder -import io.element.android.tests.testutils.lambda.value import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test @@ -191,47 +189,6 @@ class DefaultFtueServiceTest { assertThat(awaitItem()).isEqualTo(InternalFtueState.Complete) } } - - @Test - fun `reset do the expected actions S`() = runTest { - val resetAnalyticsLambda = lambdaRecorder { } - val analyticsService = FakeAnalyticsService( - resetLambda = resetAnalyticsLambda - ) - val resetPermissionLambda = lambdaRecorder { } - val permissionStateProvider = FakePermissionStateProvider( - resetPermissionLambda = resetPermissionLambda - ) - val service = createDefaultFtueService( - sdkIntVersion = Build.VERSION_CODES.S, - permissionStateProvider = permissionStateProvider, - analyticsService = analyticsService, - ) - service.reset() - resetAnalyticsLambda.assertions().isCalledOnce() - resetPermissionLambda.assertions().isNeverCalled() - } - - @Test - fun `reset do the expected actions TIRAMISU`() = runTest { - val resetLambda = lambdaRecorder { } - val analyticsService = FakeAnalyticsService( - resetLambda = resetLambda - ) - val resetPermissionLambda = lambdaRecorder { } - val permissionStateProvider = FakePermissionStateProvider( - resetPermissionLambda = resetPermissionLambda - ) - val service = createDefaultFtueService( - sdkIntVersion = Build.VERSION_CODES.TIRAMISU, - permissionStateProvider = permissionStateProvider, - analyticsService = analyticsService, - ) - service.reset() - resetLambda.assertions().isCalledOnce() - resetPermissionLambda.assertions().isCalledOnce() - .with(value("android.permission.POST_NOTIFICATIONS")) - } } internal fun TestScope.createDefaultFtueService( diff --git a/features/ftue/test/src/main/kotlin/io/element/android/features/ftue/test/FakeFtueService.kt b/features/ftue/test/src/main/kotlin/io/element/android/features/ftue/test/FakeFtueService.kt index 9217dbd22c..1dbc2c281b 100644 --- a/features/ftue/test/src/main/kotlin/io/element/android/features/ftue/test/FakeFtueService.kt +++ b/features/ftue/test/src/main/kotlin/io/element/android/features/ftue/test/FakeFtueService.kt @@ -9,18 +9,11 @@ package io.element.android.features.ftue.test import io.element.android.features.ftue.api.state.FtueService import io.element.android.features.ftue.api.state.FtueState -import io.element.android.tests.testutils.lambda.lambdaError import kotlinx.coroutines.flow.MutableStateFlow -class FakeFtueService( - private val resetLambda: () -> Unit = { lambdaError() }, -) : FtueService { +class FakeFtueService : FtueService { override val state: MutableStateFlow = MutableStateFlow(FtueState.Unknown) - override suspend fun reset() { - resetLambda() - } - suspend fun emitState(newState: FtueState) { state.emit(newState) } diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index d1041c1ba7..d3edba5833 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -72,7 +72,6 @@ dependencies { implementation(projects.features.rageshake.api) implementation(projects.features.lockscreen.api) implementation(projects.features.analytics.api) - implementation(projects.features.ftue.api) implementation(projects.features.licenses.api) implementation(projects.features.logout.api) implementation(projects.features.deactivation.api) @@ -101,7 +100,6 @@ dependencies { testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushstore.test) - testImplementation(projects.features.ftue.test) testImplementation(projects.features.invite.test) testImplementation(projects.features.rageshake.test) testImplementation(projects.features.logout.test) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt index 11c4a3c94f..50d9cf8798 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt @@ -12,7 +12,6 @@ import coil3.SingletonImageLoader import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Inject import dev.zacsweers.metro.Provider -import io.element.android.features.ftue.api.state.FtueService import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.preferences.impl.DefaultCacheService import io.element.android.libraries.core.coroutine.CoroutineDispatchers @@ -36,7 +35,6 @@ class DefaultClearCacheUseCase( private val coroutineDispatchers: CoroutineDispatchers, private val defaultCacheService: DefaultCacheService, private val okHttpClient: Provider, - private val ftueService: FtueService, private val pushService: PushService, private val seenInvitesStore: SeenInvitesStore, private val activeRoomsHolder: ActiveRoomsHolder, @@ -56,7 +54,6 @@ class DefaultClearCacheUseCase( // Clear app cache context.cacheDir.deleteRecursively() // Clear some settings - ftueService.reset() seenInvitesStore.clear() // Ensure any error will be displayed again pushService.setIgnoreRegistrationError(matrixClient.sessionId, false) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt index cfdc63984c..1e16509ad2 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt @@ -10,7 +10,6 @@ package io.element.android.features.preferences.impl.tasks import androidx.test.platform.app.InstrumentationRegistry import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.ftue.test.FakeFtueService import io.element.android.features.invite.test.InMemorySeenInvitesStore import io.element.android.features.preferences.impl.DefaultCacheService import io.element.android.libraries.matrix.api.core.SessionId @@ -41,10 +40,6 @@ class DefaultClearCacheUseCaseTest { clearCacheLambda = clearCacheLambda, ) val defaultCacheService = DefaultCacheService() - val resetFtueLambda = lambdaRecorder { } - val ftueService = FakeFtueService( - resetLambda = resetFtueLambda, - ) val setIgnoreRegistrationErrorLambda = lambdaRecorder { _, _ -> } val resetBatteryOptimizationStateResult = lambdaRecorder { } val pushService = FakePushService( @@ -59,7 +54,6 @@ class DefaultClearCacheUseCaseTest { coroutineDispatchers = testCoroutineDispatchers(), defaultCacheService = defaultCacheService, okHttpClient = { OkHttpClient.Builder().build() }, - ftueService = ftueService, pushService = pushService, seenInvitesStore = seenInvitesStore, activeRoomsHolder = activeRoomsHolder, @@ -67,7 +61,6 @@ class DefaultClearCacheUseCaseTest { defaultCacheService.clearedCacheEventFlow.test { sut.invoke() clearCacheLambda.assertions().isCalledOnce() - resetFtueLambda.assertions().isCalledOnce() setIgnoreRegistrationErrorLambda.assertions().isCalledOnce() .with(value(matrixClient.sessionId), value(false)) resetBatteryOptimizationStateResult.assertions().isCalledOnce() diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionStateProvider.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionStateProvider.kt index 0c811b7265..be9e38c4fb 100644 --- a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionStateProvider.kt +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionStateProvider.kt @@ -16,6 +16,4 @@ interface PermissionStateProvider { suspend fun setPermissionAsked(permission: String, value: Boolean) fun isPermissionAsked(permission: String): Flow - - suspend fun resetPermission(permission: String) } diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionStateProvider.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionStateProvider.kt index f61147fffa..6902247970 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionStateProvider.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionStateProvider.kt @@ -40,6 +40,4 @@ class DefaultPermissionStateProvider( override suspend fun setPermissionAsked(permission: String, value: Boolean) = permissionsStore.setPermissionAsked(permission, value) override fun isPermissionAsked(permission: String): Flow = permissionsStore.isPermissionAsked(permission) - - override suspend fun resetPermission(permission: String) = permissionsStore.resetPermission(permission) } diff --git a/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionStateProvider.kt b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionStateProvider.kt index c97057bc7d..0365ebfbbe 100644 --- a/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionStateProvider.kt +++ b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionStateProvider.kt @@ -15,7 +15,6 @@ class FakePermissionStateProvider( private var permissionGranted: Boolean = true, permissionDenied: Boolean = false, permissionAsked: Boolean = false, - private val resetPermissionLambda: (String) -> Unit = {}, ) : PermissionStateProvider { private val permissionDeniedFlow = MutableStateFlow(permissionDenied) private val permissionAskedFlow = MutableStateFlow(permissionAsked) @@ -37,10 +36,4 @@ class FakePermissionStateProvider( } override fun isPermissionAsked(permission: String): Flow = permissionAskedFlow - - override suspend fun resetPermission(permission: String) { - setPermissionAsked(permission, false) - setPermissionDenied(permission, false) - resetPermissionLambda(permission) - } } diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt index 750a6d1d17..589abf28fe 100644 --- a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt @@ -47,9 +47,4 @@ interface AnalyticsService : AnalyticsTracker, ErrorTracker { * Update analyticsId from the AccountData. */ suspend fun setAnalyticsId(analyticsId: String) - - /** - * Reset the analytics service (will ask for user consent again). - */ - suspend fun reset() } diff --git a/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt index 1df6c3ca6a..d80a8288ad 100644 --- a/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt +++ b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt @@ -70,10 +70,6 @@ class DefaultAnalyticsService( analyticsStore.setDidAskUserConsent() } - override suspend fun reset() { - analyticsStore.setDidAskUserConsent(false) - } - override suspend fun setAnalyticsId(analyticsId: String) { Timber.tag(analyticsTag.value).d("setAnalyticsId($analyticsId)") analyticsStore.setAnalyticsId(analyticsId) diff --git a/services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsServiceTest.kt b/services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsServiceTest.kt index e05a6e4208..6e65303761 100644 --- a/services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsServiceTest.kt +++ b/services/analytics/impl/src/test/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsServiceTest.kt @@ -180,20 +180,6 @@ class DefaultAnalyticsServiceTest { resetLambda.assertions().isCalledOnce() } - @Test - fun `when reset is invoked, the user consent is reset`() = runTest { - val store = FakeAnalyticsStore( - defaultDidAskUserConsent = true, - ) - val sut = createDefaultAnalyticsService( - coroutineScope = backgroundScope, - analyticsStore = store, - ) - assertThat(store.didAskUserConsentFlow.first()).isTrue() - sut.reset() - assertThat(store.didAskUserConsentFlow.first()).isFalse() - } - @Test fun `when a session is added, nothing happen`() = runTest { val sut = createDefaultAnalyticsService( diff --git a/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt b/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt index f43367c66a..db03ca5553 100644 --- a/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt +++ b/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt @@ -31,7 +31,6 @@ class NoopAnalyticsService : AnalyticsService { override suspend fun setDidAskUserConsent() = Unit override val analyticsIdFlow: Flow = flowOf("") override suspend fun setAnalyticsId(analyticsId: String) = Unit - override suspend fun reset() = Unit override fun capture(event: VectorAnalyticsEvent) = Unit override fun screen(screen: VectorAnalyticsScreen) = Unit override fun updateUserProperties(userProperties: UserProperties) = Unit diff --git a/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/FakeAnalyticsService.kt b/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/FakeAnalyticsService.kt index 081f66d4e6..f8b250e37b 100644 --- a/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/FakeAnalyticsService.kt +++ b/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/FakeAnalyticsService.kt @@ -20,7 +20,6 @@ import kotlinx.coroutines.flow.asStateFlow class FakeAnalyticsService( isEnabled: Boolean = false, didAskUserConsent: Boolean = false, - private val resetLambda: () -> Unit = {}, ) : AnalyticsService { private val isEnabledFlow = MutableStateFlow(isEnabled) override val didAskUserConsentFlow = MutableStateFlow(didAskUserConsent) @@ -65,9 +64,4 @@ class FakeAnalyticsService( override fun updateSuperProperties(updatedProperties: SuperProperties) { // No op } - - override suspend fun reset() { - didAskUserConsentFlow.value = false - resetLambda() - } } From d64b867f03c9f04fd6b22bde627f32d45ee514d2 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 22 Sep 2025 11:19:35 +0200 Subject: [PATCH 114/145] Sync Strings from Localazy (#5385) Co-authored-by: bmarty <3940906+bmarty@users.noreply.github.com> --- app/src/main/res/xml/locales_config.xml | 1 + .../src/main/res/values-cy/translations.xml | 9 +- .../src/main/res/values-fi/translations.xml | 6 +- .../src/main/res/values-eo/translations.xml | 4 + .../src/main/res/values-eo/translations.xml | 9 + .../src/main/res/values-cy/translations.xml | 2 + .../src/main/res/values-eo/translations.xml | 11 + .../src/main/res/values-fi/translations.xml | 1 + .../src/main/res/values-nb/translations.xml | 1 + .../main/res/values-zh-rTW/translations.xml | 1 + .../src/main/res/values-cy/translations.xml | 1 + .../src/main/res/values-cy/translations.xml | 3 + .../src/main/res/values-fi/translations.xml | 2 +- .../src/main/res/values-cy/translations.xml | 3 + .../src/main/res/values-eo/translations.xml | 4 + .../src/main/res/values-nb/translations.xml | 1 + .../src/main/res/values-eo/translations.xml | 8 + .../src/main/res/values-cs/translations.xml | 2 + .../src/main/res/values-cy/translations.xml | 16 + .../src/main/res/values-eo/translations.xml | 4 + .../src/main/res/values-fi/translations.xml | 1 + .../main/res/values-zh-rTW/translations.xml | 3 + .../impl/src/main/res/values/localazy.xml | 2 + .../src/main/res/values-cy/translations.xml | 8 + .../src/main/res/values-cy/translations.xml | 7 + .../src/main/res/values-fi/translations.xml | 3 + .../main/res/values-zh-rTW/translations.xml | 7 + .../src/main/res/values-cs/translations.xml | 2 + .../src/main/res/values-cy/translations.xml | 11 +- .../src/main/res/values-eo/translations.xml | 4 + .../src/main/res/values-fi/translations.xml | 8 +- .../src/main/res/values-fr/translations.xml | 1 + .../main/res/values-zh-rTW/translations.xml | 2 + .../src/main/res/values-eo/translations.xml | 44 + .../src/main/res/values-fi/translations.xml | 2 +- .../src/main/res/values-eo/translations.xml | 13 + .../src/main/res/values-cs/translations.xml | 15 +- .../src/main/res/values-cy/translations.xml | 85 +- .../src/main/res/values-eo/translations.xml | 26 + .../src/main/res/values-fi/translations.xml | 23 +- .../src/main/res/values-fr/translations.xml | 2 + .../src/main/res/values-nb/translations.xml | 13 + .../src/main/res/values-uk/translations.xml | 11 +- .../main/res/values-zh-rTW/translations.xml | 34 +- .../src/main/res/values/localazy.xml | 2 + plugins/src/main/kotlin/extension/locales.kt | 1 + .../appnav.loggedin_LoggedInView_Day_2_de.png | 4 +- .../de/appnav.root_RootView_Day_2_de.png | 4 +- ...s.call.impl.ui_CallScreenView_Day_2_de.png | 4 +- ...s.call.impl.ui_CallScreenView_Day_3_de.png | 4 +- ...l.ui_InvalidAudioDeviceDialog_Day_0_de.png | 4 +- ...erroles.impl_ChangeRolesView_Day_10_de.png | 4 +- ...cline_AcceptDeclineInviteView_Day_2_de.png | 4 +- ...eandblock_DeclineAndBlockView_Day_4_de.png | 4 +- ...es.joinroom.impl_JoinRoomView_Day_8_de.png | 4 +- ...pl.list_KnockRequestsListView_Day_5_de.png | 4 +- ...pl.list_KnockRequestsListView_Day_7_de.png | 4 +- ....leaveroom.impl_LeaveRoomView_Day_5_de.png | 4 +- ...n.impl.setup.pin_SetupPinView_Day_3_de.png | 4 +- ...n.impl.setup.pin_SetupPinView_Day_4_de.png | 4 +- ...mpl.unlock_PinUnlockViewInApp_Day_7_de.png | 4 +- ...een.impl.unlock_PinUnlockView_Day_7_de.png | 2 +- ...changeserver_ChangeServerView_Day_1_de.png | 4 +- ...changeserver_ChangeServerView_Day_2_de.png | 4 +- ...changeserver_ChangeServerView_Day_3_de.png | 4 +- ...SlidingSyncNotSupportedDialog_Day_0_de.png | 4 +- ...ogin.impl.login_LoginModeView_Day_0_de.png | 4 +- ...ogin.impl.login_LoginModeView_Day_1_de.png | 4 +- ...ogin.impl.login_LoginModeView_Day_3_de.png | 4 +- ...ogin.impl.login_LoginModeView_Day_4_de.png | 4 +- ...er_ConfirmAccountProviderView_Day_2_de.png | 4 +- ...eateaccount_CreateAccountView_Day_3_de.png | 4 +- ...ginpassword_LoginPasswordView_Day_2_de.png | 4 +- ...irect_DefaultDirectLogoutView_Day_3_de.png | 4 +- ....impl_AccountDeactivationView_Day_2_de.png | 4 +- ....impl_AccountDeactivationView_Day_4_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_6_de.png | 4 +- ...tachments.preview_AttachmentsView_5_de.png | 4 +- ...tachments.preview_AttachmentsView_6_de.png | 4 +- ...tachments.preview_AttachmentsView_8_de.png | 4 +- ...ew_VideoQualitySelectorDialog_Day_0_de.png | 4 +- ...l.forward_ForwardMessagesView_Day_3_de.png | 2 +- ...s.messages.impl.link_LinkView_Day_1_de.png | 4 +- ...d.list_PinnedMessagesListView_Day_0_de.png | 4 +- ...impl.report_ReportMessageView_Day_4_de.png | 4 +- ...e.focus_FocusRequestStateView_Day_1_de.png | 4 +- ...e.focus_FocusRequestStateView_Day_2_de.png | 4 +- ...e.focus_FocusRequestStateView_Day_3_de.png | 4 +- ...es.messages.impl_MessagesView_Day_9_de.png | 4 +- ...ll.impl.create_CreatePollView_Day_7_de.png | 4 +- ...ed_VideoQualitySelectorDialog_Day_0_de.png | 4 +- ...efaultNotificationSettingView_Day_3_de.png | 4 +- ...ons_NotificationSettingsView_Day_11_de.png | 4 +- ...ions_NotificationSettingsView_Day_3_de.png | 4 +- ...ions_NotificationSettingsView_Day_4_de.png | 4 +- ...ions_NotificationSettingsView_Day_6_de.png | 4 +- ...ions_NotificationSettingsView_Day_7_de.png | 4 +- ....impl.bugreport_BugReportView_Day_4_de.png | 4 +- ...eportroom.impl_ReportRoomView_Day_4_de.png | 4 +- ...er.impl_RoomAliasResolverView_Day_1_de.png | 4 +- ...er.impl_RoomAliasResolverView_Day_2_de.png | 4 +- ...impl.edit_RoomDetailsEditView_Day_7_de.png | 4 +- ..._RoomNotificationSettingsView_Day_3_de.png | 4 +- ..._RoomNotificationSettingsView_Day_5_de.png | 4 +- ...ons_ChangeRoomPermissionsView_Day_5_de.png | 4 +- ...sions_RolesAndPermissionsView_Day_4_de.png | 4 +- ...sions_RolesAndPermissionsView_Day_5_de.png | 4 +- ...sions_RolesAndPermissionsView_Day_7_de.png | 2 +- ...rivacy_SecurityAndPrivacyViewDark_7_de.png | 4 +- ...ivacy_SecurityAndPrivacyViewLight_7_de.png | 4 +- ...impl_RoomMemberModerationView_Day_4_de.png | 4 +- ...impl_RoomMemberModerationView_Day_6_de.png | 4 +- ...sable_SecureBackupDisableView_Day_3_de.png | 4 +- ...ureBackupEnterRecoveryKeyView_Day_3_de.png | 4 +- ...et.root_ResetIdentityRootView_Day_1_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_6_de.png | 4 +- ...p_SecureBackupSetupViewChange_Day_4_de.png | 4 +- ...l.setup_SecureBackupSetupView_Day_4_de.png | 4 +- ...features.share.impl_ShareView_Day_3_de.png | 2 +- ...tchat.impl.root_StartChatView_Day_2_de.png | 4 +- ...ponents.async_AsyncActionView_Day_3_de.png | 2 +- ....dialogs_ErrorDialogContent_Dialogs_de.png | 4 +- ...ErrorDialogWithDoNotShowAgain_Day_0_de.png | 4 +- ...omponents.dialogs_ErrorDialog_Day_0_de.png | 4 +- ....dialogs_RetryDialogContent_Dialogs_de.png | 4 +- ...omponents.dialogs_RetryDialog_Day_0_de.png | 4 +- ...iewer.impl.viewer_MediaViewerView_2_de.png | 4 +- ...rmissions.api_PermissionsView_Day_0_de.png | 4 +- ...rmissions.api_PermissionsView_Day_1_de.png | 4 +- ...rmissions.api_PermissionsView_Day_2_de.png | 4 +- ...rmissions.api_PermissionsView_Day_3_de.png | 4 +- ...es.apperror.impl_AppErrorView_Day_0_de.png | 4 +- screenshots/html/data.js | 1754 +++++++++-------- 133 files changed, 1441 insertions(+), 1066 deletions(-) create mode 100644 features/deactivation/impl/src/main/res/values-eo/translations.xml create mode 100644 features/ftue/impl/src/main/res/values-eo/translations.xml create mode 100644 features/home/impl/src/main/res/values-eo/translations.xml create mode 100644 features/login/impl/src/main/res/values-eo/translations.xml create mode 100644 features/logout/impl/src/main/res/values-eo/translations.xml create mode 100644 features/messages/impl/src/main/res/values-eo/translations.xml create mode 100644 features/roomdetails/impl/src/main/res/values-eo/translations.xml create mode 100644 features/securebackup/impl/src/main/res/values-eo/translations.xml create mode 100644 features/verifysession/impl/src/main/res/values-eo/translations.xml create mode 100644 libraries/ui-strings/src/main/res/values-eo/translations.xml diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml index a92d7b2ef9..72a7d32cc0 100644 --- a/app/src/main/res/xml/locales_config.xml +++ b/app/src/main/res/xml/locales_config.xml @@ -9,6 +9,7 @@ + diff --git a/features/changeroommemberroles/impl/src/main/res/values-cy/translations.xml b/features/changeroommemberroles/impl/src/main/res/values-cy/translations.xml index 53d4927f0f..4740c15888 100644 --- a/features/changeroommemberroles/impl/src/main/res/values-cy/translations.xml +++ b/features/changeroommemberroles/impl/src/main/res/values-cy/translations.xml @@ -2,7 +2,7 @@ "Gweinyddwyr yn unig" "Gwahardd pobl" - "Dileu negeseuon" + "Tynnu negeseuon" "Pawb" "Gwahodd pobl a derbyn ceisiadau i ymuno" "Cymedroli aelodau" @@ -17,13 +17,17 @@ "Golygu Gweinyddwyr" "Fyddwch chi ddim yn gallu dadwneud y weithred hon. Rydych chi\'n hyrwyddo\'r defnyddiwr i gael yr un lefel pŵer â chi." "Ychwanegu Gweinyddwr?" + "Fyddwch chi ddim yn gallu dadwneud y weithred hon. Rydych yn trosglwyddo\'r berchnogaeth i\'r defnyddwyr a ddewiswyd. Unwaith y byddwch yn gadael bydd hyn yn barhaol." + "Trosglwyddo perchnogaeth?" "Gostwng" "Fyddwch chi ddim yn gallu dadwneud y newid hwn gan eich bod yn israddio eich hun, os mai chi yw\'r defnyddiwr breintiedig olaf yn yr ystafell bydd yn amhosibl adennill breintiau." "Israddio eich hun?" "%1$s (Yn aros)" "Yn aros" "Mae gan weinyddwyr freintiau cymedrolwr yn awtomatig" + "Mae gan berchnogion freintiau gweinyddwr yn awtomatig." "Golygu Cymedrolwyr" + "Dewiswch Berchnogion" "Gweinyddwyr" "Cymedrolwyr" "Aelodau" @@ -48,15 +52,18 @@ "Dan ystyriaeth" "Gweinyddwr" "Cymedrolwr" + "Perchennog" "Aelodau\'r ystafell" "Dad-wahardd %1$s" "Gweinyddwyr" + "Gweinyddwyr a pherchnogion" "Newid fy rôl" "Israddio aelod" "Israddio cymedrolwr" "Cymedroli aelodau" "Negeseuon a chynnwys" "Cymedrolwyr" + "Perchnogion" "Caniatâd" "Ailosod caniatâd" "Ar ôl i chi ailosod caniatâd, byddwch yn colli\'r gosodiadau cyfredol." diff --git a/features/changeroommemberroles/impl/src/main/res/values-fi/translations.xml b/features/changeroommemberroles/impl/src/main/res/values-fi/translations.xml index b8ff96085a..1279d466e2 100644 --- a/features/changeroommemberroles/impl/src/main/res/values-fi/translations.xml +++ b/features/changeroommemberroles/impl/src/main/res/values-fi/translations.xml @@ -16,12 +16,12 @@ "Viestien lähettäminen" "Muokkaa ylläpitäjiä" "Et voi peruuttaa tätä toimenpidettä. Ylennät käyttäjän samalle oikeustasolle kuin sinä." - "Lisää ylläpitäjä?" + "Lisätäänkö ylläpitäjä?" "Et voi kumota tätä toimintoa. Olet siirtämässä omistajuuden valituille käyttäjille. Kun poistut, muutos on pysyvä." "Siirretäänkö omistajuus?" "Alenna" "Et voi perua tätä muutosta, koska olet alentamassa itseäsi. Jos olet viimeinen oikeutettu henkilö tässä huoneessa, oikeuksia ei voi enää saada takaisin." - "Alenna itsesi?" + "Haluatko alentaa itsesi?" "%1$s (Kutsuttu)" "(Kutsuttu)" "Ylläpitäjillä on automaattisesti valvojan oikeudet" @@ -32,7 +32,7 @@ "Valvojat" "Jäsenet" "Sinulla on tallentamattomia muutoksia" - "Tallenna muutokset?" + "Tallennetaanko muutokset?" "Tässä huoneessa ei ole porttikieltoja" "%1$d henkilö" diff --git a/features/deactivation/impl/src/main/res/values-eo/translations.xml b/features/deactivation/impl/src/main/res/values-eo/translations.xml new file mode 100644 index 0000000000..75c2c252e7 --- /dev/null +++ b/features/deactivation/impl/src/main/res/values-eo/translations.xml @@ -0,0 +1,4 @@ + + + "Delete your account information from our server." + diff --git a/features/ftue/impl/src/main/res/values-eo/translations.xml b/features/ftue/impl/src/main/res/values-eo/translations.xml new file mode 100644 index 0000000000..fae7da561c --- /dev/null +++ b/features/ftue/impl/src/main/res/values-eo/translations.xml @@ -0,0 +1,9 @@ + + + "Create a new backup password" + "Confirm this device to set up secure messaging." + "Confirm it\'s you" + "Use backup password" + "Device confirmed" + "Enter backup password" + diff --git a/features/home/impl/src/main/res/values-cy/translations.xml b/features/home/impl/src/main/res/values-cy/translations.xml index bde8ee4c19..c8417952a6 100644 --- a/features/home/impl/src/main/res/values-cy/translations.xml +++ b/features/home/impl/src/main/res/values-cy/translations.xml @@ -13,6 +13,7 @@ "Er mwyn sicrhau fyddwch chi ddim yn colli galwad bwysig, newidiwch eich gosodiadau i ganiatáu hysbysiadau sgrin lawn pan fydd eich ffôn wedi\'i gloi." "Gwella profiad eich galwadau" "Sgyrsiau" + "Gofodau" "Ydych chi\'n siŵr eich bod am wrthod y gwahoddiad i ymuno â %1$s?" "Gwrthod y gwahoddiad" "Ydych chi\'n siŵr eich bod am wrthod y sgwrs breifat hon gyda %1$s?" @@ -32,6 +33,7 @@ Am y tro, gallwch ddad-ddewis hidlwyr er mwyn gweld eich sgyrsiau eraill""Gwahoddiadau" "Does gennych chi ddim gwahoddiadau yn aros." "Blaenoriaeth Isel" + "Does gennych chi ddim sgyrsiau blaenoriaeth isel eto" "Gallwch ddad-ddewis hidlwyr er mwyn gweld eich sgyrsiau eraill" "Does gennych chi ddim sgyrsiau ar gyfer y dewis hwn" "Pobl" diff --git a/features/home/impl/src/main/res/values-eo/translations.xml b/features/home/impl/src/main/res/values-eo/translations.xml new file mode 100644 index 0000000000..0dc9b8e816 --- /dev/null +++ b/features/home/impl/src/main/res/values-eo/translations.xml @@ -0,0 +1,11 @@ + + + "Restore your account security and message history with a backup password if you have lost all your existing devices." + "Set up backup" + "Set up backup to protect your account" + "Confirm your backup password to maintain access to your message backup and message history." + "Enter your backup password" + "Forgot your backup password?" + "Your message backup is out of sync" + "Looks like you\'re using a new device. Confirm it with another connected device to access your encrypted messages." + diff --git a/features/home/impl/src/main/res/values-fi/translations.xml b/features/home/impl/src/main/res/values-fi/translations.xml index 52e8e9b9a2..31b5ff0a1a 100644 --- a/features/home/impl/src/main/res/values-fi/translations.xml +++ b/features/home/impl/src/main/res/values-fi/translations.xml @@ -33,6 +33,7 @@ Toistaiseksi voit poistaa suodattimien valinnan, jotta näet muut keskustelut."< "Kutsut" "Sinulla ei ole yhtään odottavaa kutsua." "Matala prioriteetti" + "Sinulla ei ole vielä yhtään matalan prioriteetin keskustelua" "Voit poistaa suodattimien valinnan nähdäksesi muut keskustelusi." "Sinulla ei ole sopivia keskusteluja tähän valintaan" "Ihmiset" diff --git a/features/home/impl/src/main/res/values-nb/translations.xml b/features/home/impl/src/main/res/values-nb/translations.xml index 558460a732..198bb7112d 100644 --- a/features/home/impl/src/main/res/values-nb/translations.xml +++ b/features/home/impl/src/main/res/values-nb/translations.xml @@ -13,6 +13,7 @@ "For å sikre at du aldri går glipp av en viktig samtale, må du endre innstillingene dine for å tillate fullskjermvarsler når telefonen er låst." "Forbedre samtaleopplevelsen din" "Chatter" + "Områder" "Er du sikker på at du vil takke nei til invitasjonen til å bli med i %1$s?" "Avvis invitasjon" "Er du sikker på at du vil avslå denne private chatten med %1$s?" diff --git a/features/home/impl/src/main/res/values-zh-rTW/translations.xml b/features/home/impl/src/main/res/values-zh-rTW/translations.xml index a9f1c932a0..625ce3ceb0 100644 --- a/features/home/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/home/impl/src/main/res/values-zh-rTW/translations.xml @@ -33,6 +33,7 @@ "邀請" "您沒有任何擱置中的邀請。" "低優先度" + "您尚無任何低優先程度聊天" "您可以取消選取篩選條件以檢視其他聊天" "您並無此選擇的聊天" "夥伴" diff --git a/features/joinroom/impl/src/main/res/values-cy/translations.xml b/features/joinroom/impl/src/main/res/values-cy/translations.xml index b093d94220..480ccdbb6c 100644 --- a/features/joinroom/impl/src/main/res/values-cy/translations.xml +++ b/features/joinroom/impl/src/main/res/values-cy/translations.xml @@ -18,6 +18,7 @@ "Ymuno â\'r ystafell" "Efallai y bydd angen i chi gael eich gwahodd neu fod yn aelod o ofod er mwyn ymuno." "Anfon cais i ymuno" + "Nodau a ganiateir %1$d o %2$d" "Neges (dewisol)" "Byddwch yn derbyn gwahoddiad i ymuno â\'r ystafell os caiff eich cais ei dderbyn." "Anfonwyd y cais i ymuno" diff --git a/features/leaveroom/api/src/main/res/values-cy/translations.xml b/features/leaveroom/api/src/main/res/values-cy/translations.xml index 1ce4f2f3b4..ea02d4d869 100644 --- a/features/leaveroom/api/src/main/res/values-cy/translations.xml +++ b/features/leaveroom/api/src/main/res/values-cy/translations.xml @@ -3,5 +3,8 @@ "Ydych chi\'n siŵr eich bod am adael y sgwrs hon? Dyw\'r sgwrs hon ddim yn gyhoeddus a fyddwch chi ddim yn gallu ailymuno heb wahoddiad." "Ydych chi\'n siŵr eich bod am adael yr ystafell hon? Chi yw\'r unig berson yma. Os byddwch yn gadael, fydd neb yn gallu ymuno yn y dyfodol, gan gynnwys chi." "Ydych chi\'n siŵr eich bod am adael yr ystafell hon? Dyw\'r ystafell hon ddim yn gyhoeddus a fyddwch chi ddim yn gallu ailymuno heb wahoddiad." + "Dewiswch Berchnogion" + "Chi yw unig berchennog yr ystafell hon. Mae angen i chi drosglwyddo perchnogaeth i rywun arall cyn i chi adael yr room." + "Trosglwyddo perchnogaeth" "Ydych chi\'n siŵr eich bod am adael yr ystafell?" diff --git a/features/lockscreen/impl/src/main/res/values-fi/translations.xml b/features/lockscreen/impl/src/main/res/values-fi/translations.xml index ae2abef6e8..02df7528e5 100644 --- a/features/lockscreen/impl/src/main/res/values-fi/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-fi/translations.xml @@ -9,7 +9,7 @@ "Salli biometrinen tunnistus" "Poista PIN-koodi" "Haluatko varmasti poistaa PIN-koodin?" - "Poista PIN-koodi?" + "Poistetaanko PIN-koodi?" "Salli %1$s" "Käytän mieluummin PIN-koodia" "Säästä aikaa ja ota käyttöön %1$s" diff --git a/features/login/impl/src/main/res/values-cy/translations.xml b/features/login/impl/src/main/res/values-cy/translations.xml index a9e4b61541..b8988a9889 100644 --- a/features/login/impl/src/main/res/values-cy/translations.xml +++ b/features/login/impl/src/main/res/values-cy/translations.xml @@ -13,6 +13,9 @@ "Arall" "Defnyddiwch ddarparwr cyfrif gwahanol, fel eich gweinydd preifat eich hun neu gyfrif gwaith." "Newid darparwr cyfrif" + "Google Play" + "Mae angen yr ap Element Pro ar %1$s. Llwythwch ef o\'r siop." + "Mae angen Element Pro" "Doedd dim modd i ni gyrraedd y gweinydd cartref hwn. Gwiriwch eich bod wedi rhoi URL y gweinydd cartref yn gywir. Os yw\'r URL yn gywir, cysylltwch â gweinyddwr eich gweinydd cartref am ragor o help." "Dyw cydweddu llithrig ddim ar gael oherwydd problem yn y ffeil .well-known: %1$s" diff --git a/features/login/impl/src/main/res/values-eo/translations.xml b/features/login/impl/src/main/res/values-eo/translations.xml new file mode 100644 index 0000000000..47e9b3830a --- /dev/null +++ b/features/login/impl/src/main/res/values-eo/translations.xml @@ -0,0 +1,4 @@ + + + "A secure connection could not be made to the new device. Your existing connected devices are still safe and you don\'t need to worry about them." + diff --git a/features/login/impl/src/main/res/values-nb/translations.xml b/features/login/impl/src/main/res/values-nb/translations.xml index e5c4343f1b..10f554ab91 100644 --- a/features/login/impl/src/main/res/values-nb/translations.xml +++ b/features/login/impl/src/main/res/values-nb/translations.xml @@ -13,6 +13,7 @@ "Annet" "Bruk en annen kontotilbyder, for eksempel din egen private server eller en arbeidskonto." "Bytt kontotilbyder" + "Google Play" "Element Pro-appen er nødvendig på %1$s. Last den ned fra butikken." "Element Pro kreves" "Vi kunne ikke nå denne hjemmeserveren. Kontroller at du har skrevet inn hjemmeserverens URL riktig. Hvis URL-en er riktig, kontakt administratoren for hjemmeserveren din for å få mer hjelp." diff --git a/features/logout/impl/src/main/res/values-eo/translations.xml b/features/logout/impl/src/main/res/values-eo/translations.xml new file mode 100644 index 0000000000..5ba5aa6e48 --- /dev/null +++ b/features/logout/impl/src/main/res/values-eo/translations.xml @@ -0,0 +1,8 @@ + + + "Your messages were still being backed up when you went offline. Reconnect so that your messages can be backed up before signing out." + "Your messages are still being backed up" + "Your messages are still being backed up" + "Backup not set up" + "Have you saved your backup password?" + diff --git a/features/messages/impl/src/main/res/values-cs/translations.xml b/features/messages/impl/src/main/res/values-cs/translations.xml index a725337d8e..3b9ffb42a3 100644 --- a/features/messages/impl/src/main/res/values-cs/translations.xml +++ b/features/messages/impl/src/main/res/values-cs/translations.xml @@ -7,6 +7,7 @@ "Předměty" "Smajlíci a lidé" "Cestování a místa" + "Nedávné emotikony" "Symboly" "Titulky nemusí být viditelné pro lidi, kteří používají starší aplikace." "Klepnutím změníte kvalitu nahrávání videa" @@ -15,6 +16,7 @@ "Nahrání média se nezdařilo, zkuste to prosím znovu." "Maximální povolená velikost souboru je %1$s." "Soubor je pro nahrání příliš velký." + "Položka %1$d z %2$d" "Optimalizace kvality obrazu" "Probíhá zpracování…" "Zablokovat uživatele" diff --git a/features/messages/impl/src/main/res/values-cy/translations.xml b/features/messages/impl/src/main/res/values-cy/translations.xml index 16841b55f6..5591e3abd7 100644 --- a/features/messages/impl/src/main/res/values-cy/translations.xml +++ b/features/messages/impl/src/main/res/values-cy/translations.xml @@ -7,10 +7,18 @@ "Gwrthrychau" "Wynebau Hapus a Phobl" "Teithio a Llefydd" + "Emojis diweddar" "Symbolau" "Efallai na fydd capsiynau yn weladwy i bobl sy\'n defnyddio apiau hŷn." + "Tapiwch i newid ansawdd llwytho\'r fideo" + "Nid oedd modd llwytho\'r ffeil." "Wedi methu â phrosesu cyfryngau i\'w llwytho, ceisiwch eto." "Wedi methu llwytho cyfryngau, ceisiwch eto." + "Y maint ffeil mwyaf a ganiateir yw %1$s ." + "Mae\'r ffeil yn rhy fawr i\'w llwytho" + "Eitem %1$d o %2$d" + "Optimeiddio ansawdd delwedd" + "Prosesu…" "Rhwystro defnyddiwr" "Gwiriwch a ydych am guddio\'r holl negeseuon presennol ac yn y dyfodol gan y defnyddiwr hwn" "Bydd y neges hon yn cael ei hadrodd i weinyddwr eich gweinyddwr cartref. Fyddan nhw ddim yn gallu darllen unrhyw negeseuon wedi\'u hamgryptio." @@ -38,6 +46,14 @@ "Dangos llai" "Neges wedi\'i chopïo" "Does gennych chi ddim caniatâd i bostio i\'r ystafell hon" + + "Ymatebodd %1$d aelodau gyda %2$s" + "Ymatebodd %1$d aelodau gyda %2$s" + "Ymatebodd %1$d aelod gyda %2$s" + "Ymatebodd %1$d aelod gyda %2$s" + "Ymatebodd %1$d aelod gyda %2$s" + "Ymatebodd %1$d aelod gyda %2$s" + "Rydych chi wedi ymateb gyda %1$s" "Dangos llai" "Dangos rhagor" diff --git a/features/messages/impl/src/main/res/values-eo/translations.xml b/features/messages/impl/src/main/res/values-eo/translations.xml new file mode 100644 index 0000000000..a0810ca15b --- /dev/null +++ b/features/messages/impl/src/main/res/values-eo/translations.xml @@ -0,0 +1,4 @@ + + + "Message history is unavailable in this room. Confirm this device to see your message history." + diff --git a/features/messages/impl/src/main/res/values-fi/translations.xml b/features/messages/impl/src/main/res/values-fi/translations.xml index 814c2cd5c2..3e1af3ce01 100644 --- a/features/messages/impl/src/main/res/values-fi/translations.xml +++ b/features/messages/impl/src/main/res/values-fi/translations.xml @@ -7,6 +7,7 @@ "Esineet" "Hymiöt ja ihmiset" "Matkustaminen ja paikat" + "Viimeaikaiset emojit" "Symbolit" "Kuvatekstit eivät välttämättä näy ihmisille, jotka käyttävät vanhempia sovelluksia." "Napauta muuttaaksesi videon lähetyslaatua" diff --git a/features/messages/impl/src/main/res/values-zh-rTW/translations.xml b/features/messages/impl/src/main/res/values-zh-rTW/translations.xml index 7854d5a0f3..6abf951e4f 100644 --- a/features/messages/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/messages/impl/src/main/res/values-zh-rTW/translations.xml @@ -9,11 +9,14 @@ "旅行與景點" "標誌" "使用舊應用程式的使用者可能看不到標題。" + "輕點即可變更影片上傳品質" "無法上傳檔案。" "無法處理要上傳的媒體,請再試一次。" "無法上傳媒體檔案,請稍後再試。" "允許的最大檔案大小為 %1$s。" "檔案太大,無法上傳" + "最佳化影像品質" + "正在處理……" "封鎖使用者" "檢查您是否要隱藏所有來自此使用者的目前及未來的訊息" "此訊息將會回報給您的家伺服器管理員。他們將無法讀取任何已加密的訊息。" diff --git a/features/messages/impl/src/main/res/values/localazy.xml b/features/messages/impl/src/main/res/values/localazy.xml index dc9e2a1892..7b0827d792 100644 --- a/features/messages/impl/src/main/res/values/localazy.xml +++ b/features/messages/impl/src/main/res/values/localazy.xml @@ -7,6 +7,7 @@ "Objects" "Smileys & People" "Travel & Places" + "Recent emojis" "Symbols" "Captions might not be visible to people using older apps." "Tap to change the video upload quality" @@ -15,6 +16,7 @@ "Failed uploading media, please try again." "The maximum file size allowed is %1$s." "The file is too large to upload" + "Item %1$d of %2$d" "Optimise image quality" "Processing…" "Block user" diff --git a/features/poll/api/src/main/res/values-cy/translations.xml b/features/poll/api/src/main/res/values-cy/translations.xml index 3479c30674..207b2f5aeb 100644 --- a/features/poll/api/src/main/res/values-cy/translations.xml +++ b/features/poll/api/src/main/res/values-cy/translations.xml @@ -1,5 +1,13 @@ + + "%1$d y cant o\'r holl bleidleisiau" + "%1$d y cant o\'r holl bleidleisiau" + "%1$d y cant o\'r holl bleidleisiau" + "%1$d y cant o\'r holl bleidleisiau" + "%1$d y cant o\'r holl bleidleisiau" + "%1$d y cant o\'r holl bleidleisiau" + "Bydd yn dileu\'r dewis blaenorol" "Dyma\'r ateb buddugol" diff --git a/features/preferences/impl/src/main/res/values-cy/translations.xml b/features/preferences/impl/src/main/res/values-cy/translations.xml index da0308b003..9711eda179 100644 --- a/features/preferences/impl/src/main/res/values-cy/translations.xml +++ b/features/preferences/impl/src/main/res/values-cy/translations.xml @@ -13,6 +13,13 @@ "Llwythwch i fyny lluniau a fideos yn gynt a lleihau\'r defnydd o ddata" "Optimeiddio ansawdd y cyfryngau" "Cymedroli a Diogelwch" + "Optimeiddio delweddau\'n awtomatig ar gyfer llwytho cyflymach a meintiau ffeiliau llai." + "Optimeiddio ansawdd llwytho delweddau" + "%1$s Tapiwch yma i newid." + "Uchel (1080p)" + "Isel (480c)" + "Safonol (720p)" + "Ansawdd lwytho fideo" "Darparwr hysbysiad gwthio" "Analluogi\'r golygydd testun cyfoethog i deipio Markdown â llaw." "Derbynebau darllen" diff --git a/features/preferences/impl/src/main/res/values-fi/translations.xml b/features/preferences/impl/src/main/res/values-fi/translations.xml index 19c87492fb..1240b620e9 100644 --- a/features/preferences/impl/src/main/res/values-fi/translations.xml +++ b/features/preferences/impl/src/main/res/values-fi/translations.xml @@ -16,6 +16,9 @@ "Optimoi kuvat automaattisesti nopeampia lähetysnopeuksia ja pienempiä tiedostokokoja varten." "Optimoi kuvien lähetyslaatu" "%1$s. Napauta tästä vaihtaaksesi." + "Korkea (1080p)" + "Matala (480p)" + "Normaali (720p)" "Videon lähetyslaatu" "Push-ilmoitusten tarjoaja" "Ota rikastettu tekstieditori pois käytöstä, jotta voit kirjoittaa Markdownia manuaalisesti." diff --git a/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml b/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml index 52630e1c7b..bda2b085a5 100644 --- a/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml @@ -13,6 +13,13 @@ "上傳照片與影片更快且減少資料使用量" "最佳化媒體品質" "管理與安全" + "自動最佳化影像以提供更快的上傳速度與較小的檔案大小。" + "最佳化影像上傳品質" + "%1$s。輕點此處以變更。" + "高 (1080p)" + "低 (480p)" + "標準 (720p)" + "視訊上傳品質" "推播通知提供者" "手動輸入 Markdown,停用格式化文字編輯器。" "已讀回條" diff --git a/features/roomdetails/impl/src/main/res/values-cs/translations.xml b/features/roomdetails/impl/src/main/res/values-cs/translations.xml index 9cc7f7b45d..e5186f1d4f 100644 --- a/features/roomdetails/impl/src/main/res/values-cs/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-cs/translations.xml @@ -50,6 +50,8 @@ "Při načítání nastavení oznámení došlo k chybě." "Ztišení této místnosti se nezdařilo, zkuste to prosím znovu." "Nepodařilo se zrušit ztišení této místnosti, zkuste to prosím znovu." + "Nezavírejte aplikaci, dokud neskončíte." + "Příprava pozvánek…" "Pozvat přátele" "Opustit konverzaci" "Opustit místnost" diff --git a/features/roomdetails/impl/src/main/res/values-cy/translations.xml b/features/roomdetails/impl/src/main/res/values-cy/translations.xml index 80726aa1f8..40c404d69b 100644 --- a/features/roomdetails/impl/src/main/res/values-cy/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-cy/translations.xml @@ -7,7 +7,7 @@ "Pleidleisiau" "Gweinyddwyr yn unig" "Gwahardd pobl" - "Dileu negeseuon" + "Tynnu negeseuon" "Pawb" "Gwahodd pobl a derbyn ceisiadau i ymuno" "Cymedroli aelodau" @@ -22,13 +22,17 @@ "Golygu Gweinyddwyr" "Fyddwch chi ddim yn gallu dadwneud y weithred hon. Rydych chi\'n hyrwyddo\'r defnyddiwr i gael yr un lefel pŵer â chi." "Ychwanegu Gweinyddwr?" + "Fyddwch chi ddim yn gallu dadwneud y weithred hon. Rydych yn trosglwyddo\'r berchnogaeth i\'r defnyddwyr a ddewiswyd. Unwaith y byddwch yn gadael bydd hyn yn barhaol." + "Trosglwyddo perchnogaeth?" "Gostwng" "Fyddwch chi ddim yn gallu dadwneud y newid hwn gan eich bod yn israddio eich hun, os mai chi yw\'r defnyddiwr breintiedig olaf yn yr ystafell bydd yn amhosibl adennill breintiau." "Israddio eich hun?" "%1$s (Yn aros)" "Yn aros" "Mae gan weinyddwyr freintiau cymedrolwr yn awtomatig" + "Mae gan berchnogion freintiau gweinyddwr yn awtomatig." "Golygu Cymedrolwyr" + "Dewiswch Berchnogion" "Gweinyddwyr" "Cymedrolwyr" "Aelodau" @@ -46,6 +50,8 @@ "Digwyddodd gwall wrth lwytho gosodiadau hysbysu." "Wedi methu tewi\'r ystafell hon, ceisiwch eto." "Wedi methu dad-dewi\'r ystafell hon, ceisiwch eto." + "Peidiwch â chau\'r ap nes ei fod wedi gorffen." + "Wrthi\'n paratoi gwahoddiadau…" "Gwahodd pobl" "Gadael y sgwrs" "Gadael yr ystafell" @@ -83,6 +89,7 @@ "Dan ystyriaeth" "Gweinyddwr" "Cymedrolwr" + "Perchennog" "Aelodau\'r ystafell" "Dad-wahardd %1$s" "Caniatáu gosodiad personol" @@ -100,12 +107,14 @@ "Crybwylliadau ac Allweddeiriau\'n unig" "Yn yr ystafell hon, rhowch wybod i mi am" "Gweinyddwyr" + "Gweinyddwyr a pherchnogion" "Newid fy rôl" "Israddio aelod" "Israddio cymedrolwr" "Cymedroli aelodau" "Negeseuon a chynnwys" "Cymedrolwyr" + "Perchnogion" "Caniatâd" "Ailosod caniatâd" "Ar ôl i chi ailosod caniatâd, byddwch yn colli\'r gosodiadau cyfredol." diff --git a/features/roomdetails/impl/src/main/res/values-eo/translations.xml b/features/roomdetails/impl/src/main/res/values-eo/translations.xml new file mode 100644 index 0000000000..46471ca4f3 --- /dev/null +++ b/features/roomdetails/impl/src/main/res/values-eo/translations.xml @@ -0,0 +1,4 @@ + + + "Messages are secured with locks. Only you and the recipients can unlock them." + diff --git a/features/roomdetails/impl/src/main/res/values-fi/translations.xml b/features/roomdetails/impl/src/main/res/values-fi/translations.xml index 04c1411e50..e77b0ab2c6 100644 --- a/features/roomdetails/impl/src/main/res/values-fi/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fi/translations.xml @@ -21,12 +21,12 @@ "Viestien lähettäminen" "Muokkaa ylläpitäjiä" "Et voi peruuttaa tätä toimenpidettä. Ylennät käyttäjän samalle oikeustasolle kuin sinä." - "Lisää ylläpitäjä?" + "Lisätäänkö ylläpitäjä?" "Et voi kumota tätä toimintoa. Olet siirtämässä omistajuuden valituille käyttäjille. Kun poistut, muutos on pysyvä." "Siirretäänkö omistajuus?" "Alenna" "Et voi perua tätä muutosta, koska olet alentamassa itseäsi. Jos olet viimeinen oikeutettu henkilö tässä huoneessa, oikeuksia ei voi enää saada takaisin." - "Alenna itsesi?" + "Haluatko alentaa itsesi?" "%1$s (Kutsuttu)" "(Kutsuttu)" "Ylläpitäjillä on automaattisesti valvojan oikeudet" @@ -37,7 +37,7 @@ "Valvojat" "Jäsenet" "Sinulla on tallentamattomia muutoksia" - "Tallenna muutokset?" + "Tallennetaanko muutokset?" "Lisää aihe" "Salattu" "Ei salattu" @@ -50,6 +50,8 @@ "Ilmoitusasetuksia ladattaessa tapahtui virhe." "Tämän huoneen mykistäminen epäonnistui, yritä uudelleen." "Tämän huoneen mykistyksen poistaminen epäonnistui, yritä uudelleen." + "Älä sulje sovellusta ennen kuin se on valmis." + "Valmistellaan kutsuja…" "Kutsu ihmisiä" "Poistu keskustelusta" "Poistu huoneesta" diff --git a/features/roomdetails/impl/src/main/res/values-fr/translations.xml b/features/roomdetails/impl/src/main/res/values-fr/translations.xml index 066ce1ee0f..feea21919d 100644 --- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml @@ -50,6 +50,7 @@ "Une erreur s’est produite lors du chargement des paramètres de notification." "Échec de la mise en sourdine de ce salon, veuillez réessayer." "Échec de la désactivation de la mise en sourdine de ce salon, veuillez réessayer." + "Préparation des invitations…" "Inviter des amis" "Quitter la discussion" "Quitter le salon" diff --git a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml index d2d6d0ef90..035de6fa4d 100644 --- a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml @@ -50,6 +50,8 @@ "載入通知設定時發生錯誤。" "無法關閉聊天室通知,請再試一次。" "無法開啟聊天室通知,請再試一次。" + "完成前請勿關閉應用程式。" + "正在準備邀請……" "邀請夥伴" "離開對話" "離開聊天室" diff --git a/features/securebackup/impl/src/main/res/values-eo/translations.xml b/features/securebackup/impl/src/main/res/values-eo/translations.xml new file mode 100644 index 0000000000..e3ea61ec1c --- /dev/null +++ b/features/securebackup/impl/src/main/res/values-eo/translations.xml @@ -0,0 +1,44 @@ + + + "Delete message backup" + "Store your account security and messages securely on the server. This will allow you to view your message history on any new devices. %1$s." + "Message backup" + "Turn on message backup to set it up." + "Upload messages from this device" + "Allow message backup" + "Change backup password" + "Restore your account security and message history with a backup password if you\'ve lost all your existing devices." + "Enter backup password" + "Your message backup is currently out of sync." + "Set up backup" + "When asked to confirm your device, select %1$s" + "Follow the instructions to create a new backup password" + "Save your new backup password in a password manager or encrypted note" + "You will need to confirm all your existing devices and verify contacts again" + "Only start fresh if you don\'t have access to another signed-in device and you\'ve lost your backup password." + "Can\'t confirm? You\'ll need to start fresh." + "Deleting message backup will remove your account security and messages from the server and turn off the following security features:" + "Are you sure you want to turn off message backup and delete it?" + "Get a new backup password if you\'ve lost your existing one. After changing your backup password, your old one will no longer work." + "Generate a new backup password" + "Backup password changed" + "Change backup password?" + "Please try again to confirm access to your message backup." + "Incorrect backup password" + "You might have seen the terms \"recovery key\", \"security key\" or \"security phrase\" instead of \"backup password\". Don\'t worry, this is all the same." + "Backup password confirmed" + "Enter your backup password" + "Copied backup password" + "Save backup password" + "Write down this backup password somewhere safe, like a password manager, encrypted note, or a physical safe." + "Tap to copy backup password" + "Save your backup password somewhere safe" + "You will not be able to access your new backup password after this step." + "Have you saved your backup password?" + "Your message backup is protected by a backup password. If you need a new backup password after setup, you can recreate it by selecting ‘Change backup password’." + "Generate your backup password" + "Backup setup successful" + "Set up backup" + "Are you sure you want to start fresh?" + "Confirm that you want to start fresh." + diff --git a/features/securebackup/impl/src/main/res/values-fi/translations.xml b/features/securebackup/impl/src/main/res/values-fi/translations.xml index 7daf180c6b..4a0cc4e34d 100644 --- a/features/securebackup/impl/src/main/res/values-fi/translations.xml +++ b/features/securebackup/impl/src/main/res/values-fi/translations.xml @@ -37,7 +37,7 @@ "Luo uusi palautusavain" "Älä jaa tätä kenenkään kanssa!" "Palautusavain vaihdettu" - "Vaihda palautusavain?" + "Vaihdetaanko palautusavain?" "Luo uusi palautusavain" "Varmista, ettei kukaan näe tätä ruutua!" "Yritä uudelleen vahvistaaksesi pääsyn avainten säilytykseen." diff --git a/features/verifysession/impl/src/main/res/values-eo/translations.xml b/features/verifysession/impl/src/main/res/values-eo/translations.xml new file mode 100644 index 0000000000..d4b40184a1 --- /dev/null +++ b/features/verifysession/impl/src/main/res/values-eo/translations.xml @@ -0,0 +1,13 @@ + + + "Create a new backup password" + "Confirm this device to set up secure messaging." + "Confirm it\'s you" + "Use backup password" + "Device confirmed" + "Now you can trust this user when sending or receiving messages." + "Enter backup password" + "Device confirmed" + "Open the app on another confirmed device" + "For extra security, another user wants to verify you. You\'ll be shown a set of emojis to compare." + 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 c53700f5b4..f3aa72c290 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -44,7 +44,7 @@ "Odstranit reakci pomocí %1$s" "Avatar místnosti" "Odeslat soubory" - "Vyžaduje se časově omezená akce" + "Vyžaduje se časově omezená akce, na ověření máte jednu minutu" "Zobrazit heslo" "Zahájit hovor" "Místnost s náhrobkem" @@ -107,6 +107,7 @@ "Odejít" "Opustit konverzaci" "Opustit místnost" + "Opustit prostor" "Načíst více" "Spravovat účet" "Spravovat zařízení" @@ -167,6 +168,8 @@ "Upgrade k dispozici" "O aplikaci" "Zásady používání" + "Přidat účet" + "Přidat další účet" "Přidání titulku" "Pokročilá nastavení" "obrázek" @@ -184,9 +187,11 @@ "Vytváření místnosti…" "Žádost zrušena" "Místnost opuštěna" + "Opustit prostor" "Pozvánka odmítnuta" "Tmavé" "Chyba dešifrování" + "Popis" "Možnosti pro vývojáře" "ID zařízení" "Přímý chat" @@ -299,14 +304,17 @@ Důvod: %1$s." "Výsledky hledání" "Zabezpečení" "Viděno" + "Vybrat účet" "Odeslat do" "Odesílání…" "Odeslání se nezdařilo" "Odesláno" ". " "Server není podporován" + "Server je nedostupný" "URL serveru" "Nastavení" + "Sdílet prostor" "Sdílená poloha" "Odhlašování" "Něco se nepovedlo" @@ -382,6 +390,8 @@ Opravdu chcete pokračovat?" "Maximální povolená velikost souboru je: %1$s" "Vyberte kvalitu videa, které chcete nahrát." "Vyberte kvalitu nahrávání videa" + "Hledat emotikony" + "Na tomto zařízení jste již přihlášeni jako %1$s." "Váš domovský server je třeba upgradovat, aby podporoval službu Matrix Authentication Service a vytváření účtu." "Vytvoření trvalého odkazu se nezdařilo" "%1$s nemohl načíst mapu. Zkuste to prosím později." @@ -409,6 +419,9 @@ Opravdu chcete pokračovat?" "Ahoj, ozvi se mi na %1$s: %2$s" "%1$s Android" "Zatřeste zařízením pro nahlášení chyby" + "Tím budete také odstraněni ze všech místností v tomto prostoru." + "Tímto budete také odstraněni ze všech místností v tomto prostoru, včetně těch, jejichž jediným správcem jste:" + "Opustit %1$s?" "Snímek obrazovky" "%1$s: %2$s" "Možnosti" diff --git a/libraries/ui-strings/src/main/res/values-cy/translations.xml b/libraries/ui-strings/src/main/res/values-cy/translations.xml index c0360cac3a..a709e010d9 100644 --- a/libraries/ui-strings/src/main/res/values-cy/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cy/translations.xml @@ -2,6 +2,7 @@ "Ychwanegu adwaith: %1$s" "Afatar" + "Lleihau maes testun neges" "Dileu" "%1$d nodau wedi eu cynnig" @@ -12,10 +13,13 @@ "%1$d nod wedi eu cynnig" "Golygu afatar" + "Bydd y cyfeiriad llawn yn%1$s" "Manylion amgryptio" + "Ehangu maes testun neges" "Cuddio cyfrinair" "Ymuno â galwad" "Symud i\'r gwaelod" + "Symud y map i\'m lleoliad" "Crybwylliadau\'n unig" "Wedi\'i Dewi" "Crybwylliadau newydd" @@ -46,9 +50,10 @@ "Wedi dileu adwaith gyda %1$s" "Afatar ystafell" "Anfon ffeiliau" - "Mae angen gweithredu â chyfyngiad amser" + "Mae angen gweithredu o fewn amser cyfyngedig, mae gennych un funud i wirio" "Dangos y cyfrinair" "Cychwyn galwad" + "Ystafell Tombstoned" "Afatar defnyddiwr" "Dewislen defnyddiwr" "Gweld afatar" @@ -93,6 +98,7 @@ "Galluogi" "Gorffen pleidlais" "Rhoi\'r PIN" + "Gorffen" "Wedi anghofio\'ch cyfrinair?" "Ymlaen" "Mynd nôl" @@ -107,6 +113,7 @@ "Gadael" "Gadael y sgwrs" "Gadael yr ystafell" + "Gadael y gofod" "Llwytho rhagor" "Rheoli cyfrif" "Rheoli dyfeisiau" @@ -124,8 +131,8 @@ "Ymateb" "Gwrthod" "Tynnu" - "Dileu capsiwn" - "Dileu neges" + "Tynnu capsiwn" + "Tynnu neges" "Ateb" "Ateb mewn edefyn" "Adroddiadau" @@ -167,10 +174,14 @@ "Uwchraddiad ar gael" "Ynghylch" "Polisi defnydd derbyniol" + "Ychwanegu cyfrif" + "Ychwanegu cyfrif arall" "Ychwanegu capsiwn" "Gosodiadau uwch" "delwedd" "Dadansoddeg" + "Rydych wedi gadael yr ystafell" + "Rydych wedi\'ch allgofnodi o\'r sesiwn" "Gwedd" "Sain" "Defnyddwyr wedi\'u rhwystro" @@ -182,9 +193,11 @@ "Wrthi\'n creu ystafell…" "Cais wedi\'i ddiddymu" "Wedi gadael yr ystafell" + "Gofod chwith" "Wedi gwrthod y gwahoddiad" "Tywyll" "Gwall dadgryptio" + "Disgrifiad" "Dewisiadau datblygwr" "ID dyfais" "Sgwrs uniongyrchol" @@ -233,12 +246,12 @@ Rheswm: %1$s." "%d arall" - "%1$d aelodau" - "%1$d aelod" - "%1$d aelod" - "%1$d aelod" - "%1$d aelod" - "%1$d aelod" + "%1$d Aelodau" + "%1$d Aelod" + "%1$d Aelod" + "%1$d Aelod" + "%1$d Aelod" + "%1$d Aelod" "Neges" "Gweithredoedd neges" @@ -272,14 +285,25 @@ Rheswm: %1$s." "%d pleidlais" "%d pleidlais" + "Yn paratoi…" "Polisi preifatrwydd" "Ystafell breifat" + "Gofod preifat" "Ystafell gyhoeddus" + "Gofod cyhoeddus" "Adwaith" "Adweithiau" "Rheswm" "Allwedd adfer" "Wrthi\'n adnewyddu…" + + "%1$d atebion" + "%1$d ateb" + "%1$d ateb" + "%1$d ateb" + "%1$d ateb" + "%1$d ateb" + "Yn ymateb i %1$s" "Adrodd ar wall" "Adrodd am broblem" @@ -288,6 +312,14 @@ Rheswm: %1$s." "Ystafell" "Enw\'r ystafell" "e.e. enw eich project" + + "%1$d Ystafelloedd" + "%1$d Ystafell" + "%1$d Ystafell" + "%1$d Ystafell" + "%1$d Ystafell" + "%1$d Ystafell" + "Newidiadau wedi\'u cadw" "Cadw" "Clo sgrin" @@ -295,18 +327,30 @@ Rheswm: %1$s." "Canlyniadau chwilio" "Diogelwch" "Wedi\'i weld gan" + "Dewis cyfrif" "Anfon at" "Yn anfon…" "Methodd anfon" "Anfonwyd" ". " "Nid yw\'r gweinydd yn cael ei gynnal" + "Gweinydd yn anghyraeddadwy" "URL gweinydd" "Gosodiadau" + "Rhannu gofod" "Lleoliad yn cael ei rannu" "Allgofnodi" "Aeth rhywbeth o\'i le" "Wedi canfod mater. Ceisiwch eto." + "Gofod" + + "%1$d Gofodau" + "%1$d Gofod" + "%1$d Ofod" + "%1$d Gofod" + "%1$d Gofod" + "%1$d Gofod" + "Dechrau sgwrs…" "Sticer" "Llwyddiant" @@ -337,6 +381,12 @@ Rheswm: %1$s." "Gwirio hunaniaeth" "Gwirio defnyddiwr" "Fideo" + "Ansawdd uchel" + "Yr ansawdd gorau ond maint ffeil mwy" + "Ansawdd isel" + "Y cyflymder llwytho cyflymaf a\'r maint ffeil lleiaf" + "Ansawdd safonol" + "Cydbwysedd ansawdd a chyflymder llwytho" "Neges llais" "Yn aros…" "Yn aros am y neges hon" @@ -351,6 +401,10 @@ Rheswm: %1$s." Ydych chi\'n siŵr eich bod am barhau?" "Gwnewch yn siŵr fod y ddolen hon yn iawn" + "Dewiswch ansawdd rhagosodedig y fideos rydych chi\'n eu llwytho." + "Ansawdd llwytho fideo" + "Y maint ffeil mwyaf sy\'n cael ei ganiatáu yw:%1$s" + "Mae maint y ffeil yn rhy fawr i\'w llwytho" "Adroddwyd am yr ystafell" "Adroddwyd a gadael yr ystafell" "Cadarnhad" @@ -359,6 +413,11 @@ Ydych chi\'n siŵr eich bod am barhau?" "Rhybudd" "Dyw eich newidiadau heb gael eu cadw. Ydych chi\'n siŵr eich bod am fynd nôl?" "Cadw\'r newidiadau?" + "Y maint ffeil mwyaf sy\'n cael ei ganiatáu yw: %1$s" + "Dewiswch ansawdd y fideo rydych chi am ei llwytho." + "Dewiswch ansawdd llwytho fideo" + "Chwilio emojis" + "Rydych chi eisoes wedi mewngofnodi ar y ddyfais hon fel %1$s ." "Mae angen uwchraddio eich gweinydd cartref i gefnogi Gwasanaeth Dilysu Matrix a chreu cyfrif." "Wedi methu creu\'r ddolen barhaol" "Methodd %1$s â llwytho\'r map. Ceisiwch eto yn nes ymlaen." @@ -386,6 +445,10 @@ Ydych chi\'n siŵr eich bod am barhau?" "Hei, siaradwch â mi ar %1$s: %2$s" "Android %1$s" "Rageshake i adrodd gwall" + "Bydd hyn hefyd yn eich tynnu o bob ystafell yn y gofod hwn." + "Bydd hyn hefyd yn eich tynnu o bob ystafell yn y gofod hwn, gan gynnwys y rhai rydych chi\'n unig weinyddwr ar eu cyfer:" + "Gadael %1$s ?" + "Llun sgrin" "%1$s: %2$s" "Dewisiadau" "Tynnu %1$s" @@ -412,6 +475,7 @@ Ydych chi\'n siŵr eich bod am barhau?" "Dyw eich neges heb ei hanfon oherwydd nid yw %1$s wedi gwirio pob dyfais" "Mae un neu fwy o\'ch dyfeisiau heb eu gwirio. Gallwch anfon y neges beth bynnag, neu gallwch ei diddymu am y tro a cheisio eto yn nes ymlaen ar ôl i chi ddilysu eich holl ddyfeisiau." "Nid yw eich neges wedi\'i hanfon oherwydd nad ydych wedi gwirio un neu fwy o\'ch dyfeisiau" + "Golygu Gweinyddwyr neu Berchnogion" "Wedi methu â phrosesu cyfryngau i\'w llwytho, ceisiwch eto." "Methu â nôl manylion defnyddiwr" "Neges yn %1$s" @@ -429,6 +493,9 @@ Ydych chi\'n siŵr eich bod am barhau?" "Agor yn Google Maps" "Agor yn OpenStreetMap" "Rhannu\'r lleoliad hwn" + "Gofodau rydych wedi\'u creu neu wedi ymuno â nhw." + "%1$s • %2$s" + "Gofodau" "Heb anfon y neges oherwydd bod hunaniaeth wedi \'i ddilysu %1$s wedi\'i ailosod." "Heb anfon y neges oherwydd nid yw %1$s wedi gwirio pob dyfais." "Heb anfon y neges oherwydd nad ydych wedi gwirio un neu fwy o\'ch dyfeisiau." diff --git a/libraries/ui-strings/src/main/res/values-eo/translations.xml b/libraries/ui-strings/src/main/res/values-eo/translations.xml new file mode 100644 index 0000000000..3368f36f08 --- /dev/null +++ b/libraries/ui-strings/src/main/res/values-eo/translations.xml @@ -0,0 +1,26 @@ + + + "Manage connected devices" + "Start fresh" + "Backup password" + "Sent from an unconfirmed device" + "Sender\'s security verification has changed" + "Confirm device" + "Verify user" + "%1$s\'s security verification has changed. %2$s" + "%1$s\'s %2$s security verification has changed. %3$s" + "%1$s\'s security verification has changed." + "%1$s\'s %2$s security verification has changed. %3$s" + "You\'re about to go to your %1$s account to start fresh. Afterwards you\'ll be taken back to the app." + "Can\'t confirm? Go to your account to start fresh." + "Your message was not sent because %1$s\'s security verification has changed" + "%1$s is using one or more unconfirmed devices. You can send the message anyway, or you can cancel for now and try again later after %2$s has confirmed all their devices." + "Your message was not sent because %1$s has not confirmed all devices" + "One or more of your connected devices are unconfirmed. You can send the message anyway, or you can cancel for now and try again later after you have confirmed all of your connected devices." + "Your message was not sent because you have not confirmed one or more of your connected devices" + "Message not sent because %1$s\'s security verification has changed." + "Message not sent because %1$s has not confirmed all their devices." + "Message not sent because you have not confirmed one or more of your connected devices." + "You need to confirm this device for access to historical messages" + "This message was blocked either because you did not confirm your device or because the sender needs to verify you." + diff --git a/libraries/ui-strings/src/main/res/values-fi/translations.xml b/libraries/ui-strings/src/main/res/values-fi/translations.xml index e41c83ea73..326d67c2d9 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -2,6 +2,7 @@ "Lisää reaktio: %1$s" "Avatar" + "Pienennä viestin tekstikenttä" "Poista" "%1$d numero syötetty" @@ -10,6 +11,7 @@ "Muokkaa avataria" "Täysi osoite tulee olemaan %1$s" "Salauksen tiedot" + "Laajenna viestin tekstikenttä" "Piilota salasana" "Liity puheluun" "Siirry loppuun" @@ -88,6 +90,7 @@ "Ota käyttöön" "Lopeta kysely" "Syötä PIN-koodi" + "Valmis" "Unohditko salasanan?" "Välitä" "Takaisin" @@ -102,6 +105,7 @@ "Poistu" "Poistu keskustelusta" "Poistu huoneesta" + "Poistu tilasta" "Lataa lisää" "Hallitse tiliä" "Hallitse laitteita" @@ -162,10 +166,14 @@ "Päivitys saatavilla" "Tietoa" "Hyväksyttävän käytön käytäntö" + "Lisää tili" + "Lisää toinen tili" "Lisätään kuvatekstiä" "Edistyneet asetukset" "kuva" "Analytiikka" + "Poistuit huoneesta" + "Sinut kirjattiin ulos istunnosta" "Ulkoasu" "Ääni" "Estetyt käyttäjät" @@ -177,9 +185,11 @@ "Luodaan huonetta…" "Pyyntö peruutettu" "Poistuit huoneesta" + "Poistuit tilasta" "Kutsu hylätty" "Tumma" "Salauksen purkuvirhe" + "Kuvaus" "Kehittäjän asetukset" "Laitteen tunnus" "Yksityinen keskustelu" @@ -289,18 +299,22 @@ Syy: %1$s." "Hakutulokset" "Turvallisuus" "Nähneet henkilöt" + "Valitse tili" "Jaa" "Lähetetään…" "Lähetys epäonnistui" "Lähetetty" ". " "Palvelin ei ole tuettu" + "Palvelimeen ei saada yhteyttä" "Palvelimen osoite" "Asetukset" + "Jaa tila" "Jaettu sijainti" "Kirjaudutaan ulos" "Jokin meni pieleen" "Kohtasimme ongelman. Yritä uudelleen." + "Tila" "%1$d Tila" "%1$d Tilaa" @@ -355,6 +369,8 @@ Syy: %1$s." Haluatko varmasti jatkaa?" "Tarkista tämä linkki" + "Valitse lähettämäsi videoiden oletuslaatu." + "Videoiden lähetyslaatu" "Suurin sallittu tiedostokoko on: %1$s" "Tiedostokoko on liian suuri lähetettäväksi" "Huone ilmoitettu" @@ -364,10 +380,12 @@ Haluatko varmasti jatkaa?" "Onnistui" "Varoitus" "Muutoksiasi ei ole tallennettu. Haluatko varmasti palata takaisin?" - "Tallenna muutokset?" + "Tallennetaanko muutokset?" "Suurin sallittu tiedostokoko on: %1$s" "Valitse lähetettävän videon laatu." "Valitse videon lähetyslaatu" + "Etsi emojeja" + "Olet jo kirjautuneena tälle laitteelle käyttäjällä %1$s." "Kotipalvelimesi on päivitettävä tukemaan Matrix Authentication Serviceä ja tilin luomista." "Pysyvän linkin luominen epäonnistui" "%1$s ei pystynyt lataamaan karttaa. Yritä myöhemmin uudelleen." @@ -395,6 +413,9 @@ Haluatko varmasti jatkaa?" "Hei, keskustele kanssani %1$s -sovelluksessa: %2$s" "%1$s Android" "Raivostunut ravistaminen ilmoittaa virheestä" + "Tämä poistaa sinut myös kaikista tämän tilan huoneista." + "Tämä poistaa sinut myös kaikista tämän tilan huoneista, mukaan lukien ne, joissa olet ainoa ylläpitäjä:" + "Haluatko poistua tilasta %1$s?" "Näyttökuva" "%1$s: %2$s" "Vaihtoehdot" 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 24cc58f41c..506a0936d9 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -187,6 +187,7 @@ "Invitation refusée" "Sombre" "Erreur de déchiffrement" + "Description" "Options pour les développeurs" "Identifiant de session" "Discussion à deux" @@ -303,6 +304,7 @@ Raison : %1$s." "Envoyé" ". " "Serveur non pris en charge" + "Serveur inaccessible" "URL du serveur" "Paramètres" "Position partagée" diff --git a/libraries/ui-strings/src/main/res/values-nb/translations.xml b/libraries/ui-strings/src/main/res/values-nb/translations.xml index 1997298944..24594c782e 100644 --- a/libraries/ui-strings/src/main/res/values-nb/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nb/translations.xml @@ -257,7 +257,9 @@ "Forbereder…" "Retningslinjer for personvern" "Privat rom" + "Privat område" "Offentlig rom" + "Offentlig område" "Reaksjon" "Reaksjoner" "Årsak" @@ -274,6 +276,10 @@ "Rom" "Romnavn" "f.eks. prosjektnavnet ditt" + + "%1$d Rom" + "%1$d Rom" + "Lagrede endringer" "Lagrer" "Skjermlås" @@ -292,6 +298,10 @@ "Logger av" "Noe gikk galt" "Vi har støtt på et problem. Vennligst prøv igjen." + + "%1$d Område" + "%1$d Områder" + "Starter chat…" "Klistremerke" "Suksess" @@ -411,6 +421,9 @@ Er du sikker på at du vil fortsette?" "Åpne i Google Maps" "Åpne i OpenStreetMap" "Del denne lokasjonen" + "Områder du har opprettet eller blitt med i." + "%1$s • %2$s" + "Områder" "Meldingen ble ikke sendt fordi %1$ss verifiserte identitet er tilbakestilt." "Meldingen ble ikke sendt fordi %1$s ikke har verifisert alle enheter." "Meldingen ble ikke sendt fordi du ikke har verifisert en eller flere av enhetene dine." 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 dfd5c19053..1afd19dc3a 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -2,6 +2,7 @@ "Додати реакцію: %1$s" "Аватар" + "Згорнути поле тексту повідомлення" "Видалити" "Введена %1$d цифра" @@ -11,6 +12,7 @@ "Редагувати аватар" "Повна адреса буде %1$s" "Подробиці шифрування" + "Розгорнути текстове поле повідомлення" "Cховати пароль" "Приєднатися до виклику" "Перейти вниз" @@ -42,7 +44,7 @@ "Прибрати реакцію %1$s" "Аватар кімнати" "Надіслати файли" - "Необхідно виконати дію, обмежену в часі" + "Необхідно виконати дію, обмежену в часі, у вас є одна хвилина для верифікації" "Показати пароль" "Розпочати виклик" "Кімната більше не використовується" @@ -165,10 +167,14 @@ "Доступне оновлення" "Відомості" "Політика прийнятного використання" + "Додати обліковий запис" + "Додати ще один обліковий запис" "Додавання підпису" "Додаткові налаштування" "зображення" "Аналітика" + "Ви вийшли з кімнати" + "Ви вийшли з сеансу" "Тема" "Аудіо" "Заблоковані користувачі" @@ -297,6 +303,7 @@ "Результати пошуку" "Безпека" "Переглянули" + "Вибрати обліковий запис" "Надіслати до" "Надсилання…" "Не вдалося надіслати" @@ -380,6 +387,8 @@ "Максимально дозволений розмір файлу: %1$s" "Виберіть якість відео, яке ви хочете вивантажити." "Виберіть якість вивантажуваного відео" + "Пошук емодзі" + "Ви вже ввійшли на цьому пристрої як %1$s." "Ваш домашній сервер потрібно оновити, щоб він підтримував службу автентифікації Matrix і створення облікових записів." "Не вдалося створити постійне посилання" "%1$s не може завантажити мапу. Повторіть спробу пізніше." diff --git a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml index fd3f6a13e0..93b486e173 100644 --- a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml @@ -2,6 +2,7 @@ "新增反應:%1$s" "大頭貼" + "最小化訊息文字欄位" "刪除" "已輸入 %1$d 個位數" @@ -9,6 +10,7 @@ "編輯大頭照" "完整地址為 %1$s" "加密詳細資訊" + "展開訊息文字欄位" "隱藏密碼" "加入通話" "跳至底部" @@ -38,7 +40,7 @@ "移除反應 %1$s" "聊天室大頭照" "傳送檔案" - "需要限時動作" + "需要限時動作,您有一分鐘可以驗證" "顯示密碼" "開始通話" "墓碑聊天室" @@ -86,6 +88,7 @@ "啟用" "結束投票" "輸入 PIN 碼" + "結束" "忘記密碼?" "轉寄" "返回" @@ -100,6 +103,7 @@ "離開" "離開對話" "離開聊天室" + "離開空間" "載入更多" "管理帳號" "管理裝置" @@ -160,10 +164,14 @@ "可升級" "關於" "可接受使用政策" + "新增帳號" + "新增其他帳號" "新增標題" "進階設定" "影像" "分析" + "您離開了聊天室" + "您已登出工作階段" "外觀" "音訊" "封鎖的使用者" @@ -175,9 +183,11 @@ "正在建立聊天室…" "請求已取消" "已離開聊天室" + "離開空間" "邀請被拒絕" "深色" "解密錯誤" + "描述" "開發者選項" "裝置 ID" "私訊" @@ -282,18 +292,21 @@ "搜尋結果" "安全性" "已讀" + "選取帳號" "傳送給" "傳送中…" "傳送失敗" "已傳送" ". " "伺服器不支援" + "無法連線至伺服器" "伺服器 URL" "設定" "位置分享" "正在登出" "有錯誤發生" "我們了遇到了問題。請再試一次。" + "空間" "%1$d 個空間" @@ -327,6 +340,12 @@ "驗證身份" "驗證使用者" "影片" + "高品質" + "品質最佳但檔案較大" + "低品質" + "最快的上傳速度且檔案最小" + "標準品質" + "品質與上傳速度的平衡" "語音訊息" "等待中…" "等待此則訊息" @@ -341,6 +360,10 @@ 您確定您想要繼續嗎?" "仔細檢查此連結" + "選取您上傳的視訊預設品質。" + "視訊上傳品質" + "允許的最大檔案大小為:%1$s" + "檔案太大,無法上傳" "聊天室已回報" "回報並離開聊天室" "確認" @@ -349,6 +372,11 @@ "警告" "變更尚未儲存,您確定要返回嗎?" "是否儲存變更?" + "最大允許的檔案大小為:%1$s" + "選取您要上傳的視訊的品質。" + "選取視訊上傳品質" + "搜尋表情符號" + "您已在此裝置上以 %1$s 的身份登入。" "您的家伺服器需要升級才能支援 Matrix Authentication Service 與帳號建立。" "無法建立永久連結" "%1$s無法載入地圖。請稍後再試。" @@ -376,6 +404,9 @@ "嘿,來 %1$s 和我聊天:%2$s" "%1$s Android" "憤怒搖晃以回報臭蟲" + "這也會將您從此空間中的所有聊天室移除。" + "這也會將您從此空間中的所有聊天室移除,包含您是唯一管理員的聊天室:" + "離開 %1$s?" "螢幕截圖" "%1$s:%2$s" "選項" @@ -398,6 +429,7 @@ "未傳送您的訊息,因為 %1$s 尚未驗證所有裝置。" "您的一個或多個裝置未經驗證。您仍可傳送訊息,也可以取消並在您驗證您的所有裝置後再試一次。" "因為您尚未驗證一個或多個裝置,因為未傳送您的訊息" + "編輯管理員或擁有者" "無法處理要上傳的媒體,請再試一次。" "無法擷取使用者詳細資訊" "%1$s 中的訊息" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 78d3ca5fdc..2e678e6c28 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -246,6 +246,7 @@ Reason: %1$s." "%1$s (%2$s)" "No results" "No room name" + "No space name" "Not encrypted" "Offline" "Open source licenses" @@ -309,6 +310,7 @@ Reason: %1$s." "Server unreachable" "Server URL" "Settings" + "Share space" "Shared location" "Signing out" "Something went wrong" diff --git a/plugins/src/main/kotlin/extension/locales.kt b/plugins/src/main/kotlin/extension/locales.kt index 31d59b73b8..93431455a5 100644 --- a/plugins/src/main/kotlin/extension/locales.kt +++ b/plugins/src/main/kotlin/extension/locales.kt @@ -12,6 +12,7 @@ val locales = setOf( "el", "en", "en-rUS", + "eo", "es", "et", "eu", diff --git a/screenshots/de/appnav.loggedin_LoggedInView_Day_2_de.png b/screenshots/de/appnav.loggedin_LoggedInView_Day_2_de.png index 72abca606b..9d5c4e5c4e 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:3f8b7d3d94c01ccaf611b5fdb0fb8ea406c5c272d5eb9558cf80648a8f281917 -size 38180 +oid sha256:ec276c2ceeeb57006ff4ad5b45e772efe8240adf461297b92ddc1a70d52e1839 +size 38187 diff --git a/screenshots/de/appnav.root_RootView_Day_2_de.png b/screenshots/de/appnav.root_RootView_Day_2_de.png index 456fea227e..51212b80c7 100644 --- a/screenshots/de/appnav.root_RootView_Day_2_de.png +++ b/screenshots/de/appnav.root_RootView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c6b161fcc127ce493ad38d8e7b54ae7c4c588a2fba7c06cbf9a6b8f6a404921 -size 21806 +oid sha256:5cd2f0f141c1195c450c42d0d0af52db289162442527bb54127bb1b23f0c4333 +size 21781 diff --git a/screenshots/de/features.call.impl.ui_CallScreenView_Day_2_de.png b/screenshots/de/features.call.impl.ui_CallScreenView_Day_2_de.png index 7cac8ad21d..f63cfd6ee8 100644 --- a/screenshots/de/features.call.impl.ui_CallScreenView_Day_2_de.png +++ b/screenshots/de/features.call.impl.ui_CallScreenView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3703e9876fcbf94befc13f8f7fc91c266fc0dea558f84288c612623d3a1cf63f -size 11101 +oid sha256:4c16876ec7bd2b6823d16f23135ccabbcb0c85b860b467bfce0373e1f3db76cf +size 11095 diff --git a/screenshots/de/features.call.impl.ui_CallScreenView_Day_3_de.png b/screenshots/de/features.call.impl.ui_CallScreenView_Day_3_de.png index 82ac489296..d9d4d8cc4f 100644 --- a/screenshots/de/features.call.impl.ui_CallScreenView_Day_3_de.png +++ b/screenshots/de/features.call.impl.ui_CallScreenView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:486f72ab9be5c85ec5710f2b463801066b57225dc3e707416d067385ea7bb31d -size 19033 +oid sha256:ab0c61a6049caddac4880fc8605e169351af36f87cb16dbbeab3c5f7e9575796 +size 19029 diff --git a/screenshots/de/features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_de.png b/screenshots/de/features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_de.png index def691ef78..616c9b651c 100644 --- a/screenshots/de/features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_de.png +++ b/screenshots/de/features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:64dcd14f14ab5ec321f6988c459e6fb7b2675baa26864e6f5eae86b8e89509e2 -size 23452 +oid sha256:e959b0af86942bdf6680e3865f2d093644ce3f9a7b56bb7fe84c30c6e1639b27 +size 23454 diff --git a/screenshots/de/features.changeroommemberroles.impl_ChangeRolesView_Day_10_de.png b/screenshots/de/features.changeroommemberroles.impl_ChangeRolesView_Day_10_de.png index 5ea694a14c..0e4b5b1562 100644 --- a/screenshots/de/features.changeroommemberroles.impl_ChangeRolesView_Day_10_de.png +++ b/screenshots/de/features.changeroommemberroles.impl_ChangeRolesView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48daacb9a588911cfde9968b837d9bd0a658b0004a0202b5b8b15a7a2394ce31 -size 53128 +oid sha256:12634dceaef537d5431771d900e476409d7efd4cca1d278c21ef424d609e0596 +size 53107 diff --git a/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png b/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png index 7120d50aba..ecd9db7dbf 100644 --- a/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png +++ b/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:027df6bffe7bed2239c06b9225dd1facd4a66191e179c781d40581e3e8240fd2 -size 31657 +oid sha256:c139e49e6fb3c7aa0f94f2e391cf82160b0dec0609a899af1910522d972ed39f +size 31633 diff --git a/screenshots/de/features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_de.png b/screenshots/de/features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_de.png index 8ae544f54d..06c106589a 100644 --- a/screenshots/de/features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_de.png +++ b/screenshots/de/features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3351d9df8402ceab8898541e03a56a368e7acef293e718f5688725bf433323e5 -size 38646 +oid sha256:47ea6d76991c1a9d4dcd017186fc226150fe7f6fb0c3f772d9fe81c655f671fd +size 38622 diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_8_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_8_de.png index 1a93a3e94a..1e052632fd 100644 --- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_8_de.png +++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3887ef896847361799a885eca9999f81bbbff641694d1647ffd6cb01f9bccd43 -size 33980 +oid sha256:c964465b659870b6ce5b32eab2ba8c19d0b078b06660c3f14faf6e54c029763d +size 34001 diff --git a/screenshots/de/features.knockrequests.impl.list_KnockRequestsListView_Day_5_de.png b/screenshots/de/features.knockrequests.impl.list_KnockRequestsListView_Day_5_de.png index 78a7c0c1bb..f739c629e1 100644 --- a/screenshots/de/features.knockrequests.impl.list_KnockRequestsListView_Day_5_de.png +++ b/screenshots/de/features.knockrequests.impl.list_KnockRequestsListView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1bfab0ac55ce67f42d53c2e5b6d8a5d49fc0d047651546a1691886c5c421533 -size 48524 +oid sha256:cb4b0c5968cf1859485f0a88e836017ce640e9e7ecc5a8db31df0cd51012da99 +size 48479 diff --git a/screenshots/de/features.knockrequests.impl.list_KnockRequestsListView_Day_7_de.png b/screenshots/de/features.knockrequests.impl.list_KnockRequestsListView_Day_7_de.png index 282335b1cb..60d8909107 100644 --- a/screenshots/de/features.knockrequests.impl.list_KnockRequestsListView_Day_7_de.png +++ b/screenshots/de/features.knockrequests.impl.list_KnockRequestsListView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:394f8b666cb31923f088b6d101de754d613ff3d9cfef28066178af007333357e -size 44373 +oid sha256:a7f9908bb1a05de0c4e97e830f9ee543deb29d8664cad5ae5a29a5a6cb5284d1 +size 44367 diff --git a/screenshots/de/features.leaveroom.impl_LeaveRoomView_Day_5_de.png b/screenshots/de/features.leaveroom.impl_LeaveRoomView_Day_5_de.png index 2ea6aa11ca..6be223de8c 100644 --- a/screenshots/de/features.leaveroom.impl_LeaveRoomView_Day_5_de.png +++ b/screenshots/de/features.leaveroom.impl_LeaveRoomView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccb6c4a8689c8c9c309ba64fef507ce14805392ec3aee5220d6ecd1e754994fc -size 37579 +oid sha256:a66922765b357a16336992692aa74ff3d1e58868ab272008032332a66823a2ae +size 37550 diff --git a/screenshots/de/features.lockscreen.impl.setup.pin_SetupPinView_Day_3_de.png b/screenshots/de/features.lockscreen.impl.setup.pin_SetupPinView_Day_3_de.png index 022700f776..e67751b3c7 100644 --- a/screenshots/de/features.lockscreen.impl.setup.pin_SetupPinView_Day_3_de.png +++ b/screenshots/de/features.lockscreen.impl.setup.pin_SetupPinView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26e818df9c99d20c71acddb0a5697ffab3eebfa896e4ed24f79fbafd36bb9d5d -size 27780 +oid sha256:339e4dc13f6074ca938d6752878b54752f6c9002c92ebf291136079579f85bd5 +size 27776 diff --git a/screenshots/de/features.lockscreen.impl.setup.pin_SetupPinView_Day_4_de.png b/screenshots/de/features.lockscreen.impl.setup.pin_SetupPinView_Day_4_de.png index faf578f961..a7a98fafb1 100644 --- a/screenshots/de/features.lockscreen.impl.setup.pin_SetupPinView_Day_4_de.png +++ b/screenshots/de/features.lockscreen.impl.setup.pin_SetupPinView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3c7051ef748dca1730dd0e5348709228e6950b3c2fa0e5a47a2609fbbb0c3bf -size 32696 +oid sha256:fa5cf8e3bbd7116f1c8c27ac29d956929ed6a52e7b2b9a0cc425709ed83c3c1f +size 32583 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_de.png index 2e632bab83..9e2974f594 100644 --- a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_de.png +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7ee6437ca7d096d5a2ba7171a4749015da77032b3a154d3fa5124870e6392fa -size 25062 +oid sha256:02cbbc16f07b45feeb638195be476483d68dd652462f8b069a6e1492f66d0089 +size 25068 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_7_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_7_de.png index 93f749bbc9..9f22132175 100644 --- a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_7_de.png +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6ea7ae5ada8408bfae483241aa553a95cf3e4a5afe7a313942f07eabe2f32f3 +oid sha256:88c5747df737c777ca3e1fb039e6507489d2db418d46d970f25b7380ff0dfb40 size 32282 diff --git a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_1_de.png b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_1_de.png index b23fe05d44..c856f0e358 100644 --- a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_1_de.png +++ b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:628cc87a2c18dd8416ddfca2a7bde83f9254e79031bbfdbbb41663f3ebc6d0b4 -size 14401 +oid sha256:506f037d7cce42ac09efc89bff5d74475a723321af4713ed54a7caf85bfcb297 +size 14382 diff --git a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_2_de.png b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_2_de.png index ac9a633cf2..52cb399536 100644 --- a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_2_de.png +++ b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f8bf0480dbcf1edd824649000e0c01d84047c85fa3e6f7d73a43d495ee78549f -size 32391 +oid sha256:38bd30d45c29b9655f0e07e76c22d46b0e0ab5e3cce718bcdb135141a098332d +size 32396 diff --git a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_3_de.png b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_3_de.png index 3f09465793..a99f7380f6 100644 --- a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_3_de.png +++ b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b5104c3f7bcb024b7ae93fa0da6c4f310ed791805fe276cf140028d84843bab -size 16339 +oid sha256:16da7f89ea01252b4805da19a577c17be69890c45a5fd59f0d9cdadaed24be04 +size 16317 diff --git a/screenshots/de/features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_de.png b/screenshots/de/features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_de.png index ac9a633cf2..52cb399536 100644 --- a/screenshots/de/features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_de.png +++ b/screenshots/de/features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f8bf0480dbcf1edd824649000e0c01d84047c85fa3e6f7d73a43d495ee78549f -size 32391 +oid sha256:38bd30d45c29b9655f0e07e76c22d46b0e0ab5e3cce718bcdb135141a098332d +size 32396 diff --git a/screenshots/de/features.login.impl.login_LoginModeView_Day_0_de.png b/screenshots/de/features.login.impl.login_LoginModeView_Day_0_de.png index f7934c34d4..298de207db 100644 --- a/screenshots/de/features.login.impl.login_LoginModeView_Day_0_de.png +++ b/screenshots/de/features.login.impl.login_LoginModeView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:89054d2e35f11086c392d5de2dd299a76803b07b7236e403bb41c18ae991e046 -size 37021 +oid sha256:01bb49eb69c81c2d00318aed7463436f500e7a69679c05003e468459b3563c94 +size 37005 diff --git a/screenshots/de/features.login.impl.login_LoginModeView_Day_1_de.png b/screenshots/de/features.login.impl.login_LoginModeView_Day_1_de.png index 09833de090..97263af58c 100644 --- a/screenshots/de/features.login.impl.login_LoginModeView_Day_1_de.png +++ b/screenshots/de/features.login.impl.login_LoginModeView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c7ab2dc5a541481eb5e348772064a23668a481073ae7b97fb069df9b11f9597e -size 10937 +oid sha256:cd7144624be51c4bc8a4d6d59c898fc50e8607f819c4c6c0bfe75100b9cc4c2d +size 10932 diff --git a/screenshots/de/features.login.impl.login_LoginModeView_Day_3_de.png b/screenshots/de/features.login.impl.login_LoginModeView_Day_3_de.png index 7617196945..683bef00b4 100644 --- a/screenshots/de/features.login.impl.login_LoginModeView_Day_3_de.png +++ b/screenshots/de/features.login.impl.login_LoginModeView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21dbf7e2c3c9fef115de119b26ac00872336d402e0680ba951f89f8b0555e2ef -size 15807 +oid sha256:ab6bd357aaa6bfb530e596693f1c1454274784d53363525c5e8b89efd4599481 +size 15786 diff --git a/screenshots/de/features.login.impl.login_LoginModeView_Day_4_de.png b/screenshots/de/features.login.impl.login_LoginModeView_Day_4_de.png index ac9a633cf2..52cb399536 100644 --- a/screenshots/de/features.login.impl.login_LoginModeView_Day_4_de.png +++ b/screenshots/de/features.login.impl.login_LoginModeView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f8bf0480dbcf1edd824649000e0c01d84047c85fa3e6f7d73a43d495ee78549f -size 32391 +oid sha256:38bd30d45c29b9655f0e07e76c22d46b0e0ab5e3cce718bcdb135141a098332d +size 32396 diff --git a/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png index 32cb3a1eb2..49eb1c3e50 100644 --- a/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png +++ b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a77db58d9c877002568d3554a43bae126c55249910c60f772d70c00eb64924e -size 41262 +oid sha256:61d0f8e341e76fee533117b9724aec1e299519e7cff827d43b0977e7d6845ab9 +size 41284 diff --git a/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_3_de.png b/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_3_de.png index e8d43eb741..61d358271f 100644 --- a/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_3_de.png +++ b/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bfbe1b69a417a3a08dd9864e1bc4f150538b36906bd06e0c571575f64fc7a058 -size 15585 +oid sha256:f55612c2279875c0d128d124097f6ed36378e16bf4d0a2ce27126e3f76b57147 +size 15587 diff --git a/screenshots/de/features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_de.png b/screenshots/de/features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_de.png index b6252c50e3..8c48a80d25 100644 --- a/screenshots/de/features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_de.png +++ b/screenshots/de/features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c437e3747748e9421644cf1ff1988f27f685515ab2cf1c6913166b3455e03a10 -size 30421 +oid sha256:e73952f62b9f4addbf6c66e6929da91539a451660a6617ac53f995534726f52d +size 30406 diff --git a/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_3_de.png b/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_3_de.png index 460eb8cad4..251b8a0496 100644 --- a/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_3_de.png +++ b/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f87747043f62847839dc9eb80a4011d555d230a1310edeaa2c8bf6395213313 -size 20660 +oid sha256:33601bf38dab409508b12c6f864d5529fdb24d17bd54caf50502abdfe4e04ea5 +size 20636 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png index e74f9bd19a..52bed8eca4 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f3ec4d1f9787b011113b41f9868c0276784b3a9d7ce7a72d487950aa158d5b7 -size 79784 +oid sha256:1a9978fc6a551e92d64880cebac69380fa57cd793e790529db023111ea1f407c +size 79754 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png index b73d5d55f2..f53bb77866 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bbf2df2dda72fc32211778f075d00edfd47109e0fa87f5d694378a138e4c8ae -size 61833 +oid sha256:df52787c1b88af53738293ee058b67ddd08f78c857c2e3af3f006d12626cd250 +size 61807 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_6_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_6_de.png index a63166bdd8..d97f248616 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_6_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:befa9251f01f28dd09063171f7c3dad4a3f1ed58026d5c1dbe718e39edf6982c -size 27434 +oid sha256:dbb085f18507ad5448a6614bf2823879e7e6497a52eb9feb4265a3e717030b8f +size 27420 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_5_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_5_de.png index 3cf9e4fb19..f2979cc741 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_5_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9be86c06161d58cf4204791eac435bad01c166edadf07f61ea5d9019f1a5dfb -size 68306 +oid sha256:c06481e9cc1787ac90268137a145790eab9929690e162ef22e7e0b1d4796d368 +size 68291 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_6_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_6_de.png index 4e2bceba69..6d0ad528db 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_6_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:969b78ec1d869b7f06c4dec25176fe4bfcf9e6ae0522af6cb921df0d86c0240c -size 72014 +oid sha256:5a1c8211e71e899ee932c6016e1d44eceb340a55727b72f5055a7a57ade3e6e5 +size 72017 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_8_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_8_de.png index 7f21f5ba9d..0366e56484 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_8_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0dd36282dba9dadef788807726d9ee12d4d61e23c61dc0139ea812f20d96b696 -size 89662 +oid sha256:c356dd8df9ef8b414c68458828b20a709d55c3ffcd9010482c07e5e0ad501461 +size 89714 diff --git a/screenshots/de/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_de.png b/screenshots/de/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_de.png index 8037f2e7fc..f614e6eac7 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1c83af220914a1c29336486ef27e37581e663c8b7424f793ea4226f49b8c1114 -size 71882 +oid sha256:c71d15c6788611ecc0be5f75d64696d7bf68673f9c75c91d692358fedf219ba6 +size 71872 diff --git a/screenshots/de/features.messages.impl.forward_ForwardMessagesView_Day_3_de.png b/screenshots/de/features.messages.impl.forward_ForwardMessagesView_Day_3_de.png index 415bf08603..9f006b50ca 100644 --- a/screenshots/de/features.messages.impl.forward_ForwardMessagesView_Day_3_de.png +++ b/screenshots/de/features.messages.impl.forward_ForwardMessagesView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8077b421a93fb66d11503d75b558acda35947f5886c0f11d6b81dcf1c5e7653 +oid sha256:384eb7f0964c98a0f9f78085e7523086818f76c1d56e6750424cff515971e357 size 8681 diff --git a/screenshots/de/features.messages.impl.link_LinkView_Day_1_de.png b/screenshots/de/features.messages.impl.link_LinkView_Day_1_de.png index cecc9c370f..659485fa9c 100644 --- a/screenshots/de/features.messages.impl.link_LinkView_Day_1_de.png +++ b/screenshots/de/features.messages.impl.link_LinkView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:466a88dd4bcc7aa5666e248c0acf02e36d9a726754014c4c2353f4860a529ad0 -size 32255 +oid sha256:3acf4964ad6d685b5cef831d2397d46beb7f3de7cb1b062b07b513cf4bdf08a2 +size 32269 diff --git a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_de.png b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_de.png index 859a4b74f3..358c0dff18 100644 --- a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8cb6fbaa752a13e34a7d049b9cfd1048fa499d35cb99dca78ec3ea25f01a4251 -size 25033 +oid sha256:dd115b1d8b6b3d5c302d45110947cee2f9e5b1df9c6c6c7f24f750e1850e04af +size 24976 diff --git a/screenshots/de/features.messages.impl.report_ReportMessageView_Day_4_de.png b/screenshots/de/features.messages.impl.report_ReportMessageView_Day_4_de.png index 7906c74564..636abf3e9e 100644 --- a/screenshots/de/features.messages.impl.report_ReportMessageView_Day_4_de.png +++ b/screenshots/de/features.messages.impl.report_ReportMessageView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ae11374f316fc309e9fb909a06d09c2a5781bf7f223acb0dcb33fdf1d9cfb3c -size 28952 +oid sha256:4ff29d01ede74dd4bb73eaaf95969867ff27d25fc9123c81aa7746b4c660694c +size 28941 diff --git a/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_de.png index 1cb1173b12..c53dd3597d 100644 --- a/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_de.png +++ b/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a83be835af4ba5220bc17d56e430b53b363df5a53e7f4a05fb34cb0e7e9487ff -size 11513 +oid sha256:a0a43b9a921e9e6e3524f3830a4a6d8a0ac0a8185f60427146e0a683c1f68e5e +size 11516 diff --git a/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_de.png b/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_de.png index 1cb1173b12..c53dd3597d 100644 --- a/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_de.png +++ b/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a83be835af4ba5220bc17d56e430b53b363df5a53e7f4a05fb34cb0e7e9487ff -size 11513 +oid sha256:a0a43b9a921e9e6e3524f3830a4a6d8a0ac0a8185f60427146e0a683c1f68e5e +size 11516 diff --git a/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_de.png b/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_de.png index b23fe05d44..c856f0e358 100644 --- a/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_de.png +++ b/screenshots/de/features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:628cc87a2c18dd8416ddfca2a7bde83f9254e79031bbfdbbb41663f3ebc6d0b4 -size 14401 +oid sha256:506f037d7cce42ac09efc89bff5d74475a723321af4713ed54a7caf85bfcb297 +size 14382 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 66f1d91843..93a2e19fca 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:d22db7b845a7fe310bcc6d8c57e95f32b1edfb9841f9785fd9f3dc261ad7f48c -size 49579 +oid sha256:ceff1004db2bbe6cbdf2c6d62e4521b89a9c63823b6cd1c709037e3bae306302 +size 49568 diff --git a/screenshots/de/features.poll.impl.create_CreatePollView_Day_7_de.png b/screenshots/de/features.poll.impl.create_CreatePollView_Day_7_de.png index e9dc52b6e5..48641b50c0 100644 --- a/screenshots/de/features.poll.impl.create_CreatePollView_Day_7_de.png +++ b/screenshots/de/features.poll.impl.create_CreatePollView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fab6aaceb328430d33609f68f43b6133fe532e700d43235e35cbe93f403aa9e0 -size 40841 +oid sha256:1fcf6e7dc35e868539efe503ed937d978ed75c5f3f46e4f19ab52dc3bec71303 +size 40813 diff --git a/screenshots/de/features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_de.png b/screenshots/de/features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_de.png index f4ab27d051..b8ced31a50 100644 --- a/screenshots/de/features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_de.png +++ b/screenshots/de/features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da9077d093d852068db6a0c20aebf8e76ecdb64114b64b3f2db6020e8a9602f1 -size 62455 +oid sha256:8e9642babd75110581efedcf740f42d800dd8b93ff63707cf54ec273a23e6ce5 +size 62459 diff --git a/screenshots/de/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_de.png b/screenshots/de/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_de.png index c91f3101bc..b447e6eb76 100644 --- a/screenshots/de/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_de.png +++ b/screenshots/de/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a856144e5645d4624b888be7b7a0b2d7be3f40b86e01893347f700dc0e1f0acb -size 41411 +oid sha256:d5130de6e57ac0b4ada7b7a7de549cb08c1a1b48ac64cc05ab39f8d2efb41680 +size 41413 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 ae4eae6136..5837583cf1 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:33e046c38a374200a1cd8143d2d8ecb9b28fab08d58a9207df5f48d26bc6a61c -size 42847 +oid sha256:bc683b3b8b0b3ffa9da10e505559f98b2faef0dd85523d2bf21faa32956d9483 +size 42832 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_3_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_3_de.png index caeba08e69..589bdcabc5 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_3_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bab5d7148aa93d93279ba04125814702664ffc272d29e5c7288661a2fe45d4b7 -size 50021 +oid sha256:3b8df24928cda90d3e29186034cf088ebbe37a75b99e7ac8132f515e339a6bc2 +size 50019 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_4_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_4_de.png index caeba08e69..589bdcabc5 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_4_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bab5d7148aa93d93279ba04125814702664ffc272d29e5c7288661a2fe45d4b7 -size 50021 +oid sha256:3b8df24928cda90d3e29186034cf088ebbe37a75b99e7ac8132f515e339a6bc2 +size 50019 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_6_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_6_de.png index f695529b11..0fc4259316 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_6_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a62180a7f7ac07a75fbb73bb31a085c22c621b1d14db125ebaaa163f457d172 -size 47160 +oid sha256:b83ce1b120f5eca77007f7f7d957bdd3c45135f5f3e454ec68c50564924373f3 +size 47163 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_7_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_7_de.png index afa048c458..663000bae6 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_7_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4932d9acbe99d45c9b1886817eae52cbc4c4d978476020d4c229d5d5d2893980 -size 52303 +oid sha256:633b2df37189860357e7a98285f57c098e580d61cb82fdf274055e7559865a9b +size 52264 diff --git a/screenshots/de/features.rageshake.impl.bugreport_BugReportView_Day_4_de.png b/screenshots/de/features.rageshake.impl.bugreport_BugReportView_Day_4_de.png index cdcf00cf53..66088d0cd9 100644 --- a/screenshots/de/features.rageshake.impl.bugreport_BugReportView_Day_4_de.png +++ b/screenshots/de/features.rageshake.impl.bugreport_BugReportView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7def84e736b71aa50b6da5ebe2a959e54c4bef83e5d13477e1e1143e7cc3aa1c -size 57643 +oid sha256:bce0a946397aa0223be195fc0090b6bf009ed02a914879840bc445b271a37a32 +size 57646 diff --git a/screenshots/de/features.reportroom.impl_ReportRoomView_Day_4_de.png b/screenshots/de/features.reportroom.impl_ReportRoomView_Day_4_de.png index efb5e3c53f..dc2fd86233 100644 --- a/screenshots/de/features.reportroom.impl_ReportRoomView_Day_4_de.png +++ b/screenshots/de/features.reportroom.impl_ReportRoomView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4141c28d59cbc731c96f9625a0fed478d3ee18a3b0498a69f50f952b66f4053e -size 32018 +oid sha256:43c3083501e9fa128a2eab0896829f1a37ac673111d2ac7cbc3886ee1a02f884 +size 32001 diff --git a/screenshots/de/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_de.png b/screenshots/de/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_de.png index 1a93a3e94a..1e052632fd 100644 --- a/screenshots/de/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_de.png +++ b/screenshots/de/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3887ef896847361799a885eca9999f81bbbff641694d1647ffd6cb01f9bccd43 -size 33980 +oid sha256:c964465b659870b6ce5b32eab2ba8c19d0b078b06660c3f14faf6e54c029763d +size 34001 diff --git a/screenshots/de/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_de.png b/screenshots/de/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_de.png index a61ad50520..17ecc2d044 100644 --- a/screenshots/de/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_de.png +++ b/screenshots/de/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c18619e7ba34ada5b6bef1ef552c522fa1c031f148cbf36649206a1df0eba5bd -size 25568 +oid sha256:7010c3f8fcd3863d07a97ea8e07be0ce65f9a9d232b46c99888bade57462e9a6 +size 25589 diff --git a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_de.png b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_de.png index f7618097ad..87677b8e2d 100644 --- a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_de.png +++ b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0df2d9b9be192f42a172633cd07cd4686a699f12609aef93afb5d1e8a6d86cc -size 29762 +oid sha256:445db5ce8ac1d90129d2e53be3074f0c8d4518374355833c0ce3579fa9ff3394 +size 29761 diff --git a/screenshots/de/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_de.png b/screenshots/de/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_de.png index e0dd7601dd..8a3190e8a6 100644 --- a/screenshots/de/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_de.png +++ b/screenshots/de/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6182b842f646b7eda109f9e411a9a8f2a1dd8e7b807bf4239acf608426f1fa0f -size 42647 +oid sha256:bb7aae1df2a4cbfbda74c6c8812198140e54f12b7798af9a1a90500616b05595 +size 42653 diff --git a/screenshots/de/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_de.png b/screenshots/de/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_de.png index e0dd7601dd..8a3190e8a6 100644 --- a/screenshots/de/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_de.png +++ b/screenshots/de/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6182b842f646b7eda109f9e411a9a8f2a1dd8e7b807bf4239acf608426f1fa0f -size 42647 +oid sha256:bb7aae1df2a4cbfbda74c6c8812198140e54f12b7798af9a1a90500616b05595 +size 42653 diff --git a/screenshots/de/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_de.png b/screenshots/de/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_de.png index d7b6fca2bc..68d5d0381f 100644 --- a/screenshots/de/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_de.png +++ b/screenshots/de/features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a527d0177803a96bc7ae717caa9c2ca4e96f35e1da0fec42e0e6bb825132e80c -size 38849 +oid sha256:f6b9b30eecec15ac0adf1ba18dc578553770e228c944d928dc87bb308ad66a95 +size 38846 diff --git a/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_de.png b/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_de.png index bf8522617d..2540918855 100644 --- a/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_de.png +++ b/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8766a94b51ec53c8330ce901394d3fe4a92f7f736ffa617ff63e1c4511197f43 -size 43946 +oid sha256:638d958fa225877f475feb357c0d839fef8a05b876238522c9750a8b90b23358 +size 43922 diff --git a/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_de.png b/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_de.png index 96b8936d53..a61d4381bc 100644 --- a/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_de.png +++ b/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce62f7f62d097fdfc85ef2c409e6abbcce0f320aa1fa458f0622b039b3e03bfe -size 56504 +oid sha256:89d4726d9deb408e2a7fac1a71ad487b154faa9735131bd1fcbd64d0587746bc +size 56525 diff --git a/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_de.png b/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_de.png index b47952d037..23571dc46c 100644 --- a/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_de.png +++ b/screenshots/de/features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22d8c6b59b409a01ebdaa24b65cd3516d411e118d40fbb9576064e9d6a06d730 +oid sha256:c60eaa6e529c230303960d0fa3ca03eec6c010bef06bb6a46db2d1241472a312 size 43377 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_de.png index 56a7a11055..c8d111b76e 100644 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_de.png +++ b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:421174f28f650d589613e7bbad4f46541e88cd67c9e4aed789f136b900fc61ad -size 50030 +oid sha256:d685380e4b4ec9634ceab25bb989dda305000bbc63d388d308584ce9be41e900 +size 50034 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_de.png index 43ed134364..63c9d2f2ec 100644 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_de.png +++ b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25d8ecbc9477f4baa755cf01530bb3f5ad95832a6c14cd49beb3a41ee5f9f5f7 -size 52366 +oid sha256:9322e1e84b86d8deeb0ff07ce296847c54d620901fa072fbe5321c1197fac16e +size 52370 diff --git a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_de.png b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_de.png index fd881fdd55..f11c344ae6 100644 --- a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_de.png +++ b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1f142e1a18779649d19d7c031b8de83f359c36a4e1a6225e13edccf773102c5 -size 31609 +oid sha256:6dd52f4b17d3ff94b4d61db544fddfb8b449da49673ecb45a02fa297966b52f6 +size 31604 diff --git a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_de.png b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_de.png index 5e7a0b3ee0..9a626deaab 100644 --- a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_de.png +++ b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3cfc2b6376f8d8f1a20befd2b7817e5eab0a9612f3fce05290ddc5cccdade39f -size 32124 +oid sha256:5037873ed63f558691c06a63f93eca0d22dd2ec1f70aec2dcbf9481e73d16412 +size 32099 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png index f327c1d5d0..ff25ff9a77 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6837012d8b4863b5bbcdca3e2e7a038a0df2723767d54bbb3394f010e66751e3 -size 46045 +oid sha256:e3f99c41bdd09088037a6fc0e7436f71867e679e2d4f829156cf774cf5c06ec8 +size 46051 diff --git a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_de.png b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_de.png index 23d60c8cb6..c2cfc1532c 100644 --- a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_de.png +++ b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b100deda7d2a421e3d57183b17d0d5d07f4a5c791774e7f57edfc02d8d00d99 -size 51026 +oid sha256:05096ace3fae4368464a78816164680ebecf5a65b03eb9bc6fc6eb06a0a43d81 +size 50930 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 be93620283..45e32ffc99 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:aa1e4b41b792ffd847e06bfa66cf4c6aa1e0f74af84562ba2943b7ccd7b92831 -size 50160 +oid sha256:a1468fd52b8e3448bd1f8e0f3791c574565adddeda13ea8a13b2332e132522d6 +size 50128 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png index 755c6f633b..f36902ec07 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3a4d53926428ea875ba03831aaa63e499235ecfc420e3f0232653e7262221c8 -size 42153 +oid sha256:818f5f1d73b601d026f513387d76e67628142609412c0afa055d530be94db263 +size 42157 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_de.png index 1499406151..d58496d0b3 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4236d65528a408e142bee3d102fa697ec46f2279da0a3faab60b8601bfd85368 -size 51489 +oid sha256:edc3adcd73285dbaf217485d9e296a1af1ef592d65baca1fcf6ed75700d17eb3 +size 51568 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_4_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_4_de.png index 1499406151..d58496d0b3 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_4_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4236d65528a408e142bee3d102fa697ec46f2279da0a3faab60b8601bfd85368 -size 51489 +oid sha256:edc3adcd73285dbaf217485d9e296a1af1ef592d65baca1fcf6ed75700d17eb3 +size 51568 diff --git a/screenshots/de/features.share.impl_ShareView_Day_3_de.png b/screenshots/de/features.share.impl_ShareView_Day_3_de.png index 415bf08603..9f006b50ca 100644 --- a/screenshots/de/features.share.impl_ShareView_Day_3_de.png +++ b/screenshots/de/features.share.impl_ShareView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8077b421a93fb66d11503d75b558acda35947f5886c0f11d6b81dcf1c5e7653 +oid sha256:384eb7f0964c98a0f9f78085e7523086818f76c1d56e6750424cff515971e357 size 8681 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png index cb7209b068..60aa2ae9c2 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b070f5671759396846a0796cb94307a429724318a74277a388839e79cb5c5e4 -size 31873 +oid sha256:dbda304432217316c4cc028d98e6394619c9279a261a004466bd5ddf640f994f +size 31853 diff --git a/screenshots/de/libraries.designsystem.components.async_AsyncActionView_Day_3_de.png b/screenshots/de/libraries.designsystem.components.async_AsyncActionView_Day_3_de.png index 40bb8c6698..ce4f4013b5 100644 --- a/screenshots/de/libraries.designsystem.components.async_AsyncActionView_Day_3_de.png +++ b/screenshots/de/libraries.designsystem.components.async_AsyncActionView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e7f87cbe57ac1f64685dff9df668d30311898b045596b3f2c928c3606ea129c +oid sha256:1b891e2217b77873c9f33f8377a0a1643a9e461e5ec4e67b817494194f4ec60c size 10478 diff --git a/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_de.png b/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_de.png index fa50461695..80fce53231 100644 --- a/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_de.png +++ b/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:674db98a0ff8dd9628b19583bf671b8eb7eefa13f3475525e14c8a61a5e05591 -size 14286 +oid sha256:490e87db0101dcf91fe86568322cacae54b657bd66de955e0dbbff2f5402396e +size 14285 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 1b305a5b9d..a43d60ba7c 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:1e601b48a4db352012a7ce171f1ea6cf1e2241224dbec2944e9367e617348a86 -size 12864 +oid sha256:c1b59d7d1c8541af79bd99b45d5c4e7f0d17179c2f5a8f1c2feb694f92225c37 +size 12855 diff --git a/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialog_Day_0_de.png b/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialog_Day_0_de.png index bb113d1f29..61c16505c5 100644 --- a/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialog_Day_0_de.png +++ b/screenshots/de/libraries.designsystem.components.dialogs_ErrorDialog_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bc1577f7e5d3125cd432cbc346803c81e9c4f24813241f90bc0542a0b2e5aa6 -size 9278 +oid sha256:16421610dab7afeaa01e67e1b48d5cff9e516d4bead702381fd00d3dfe75cd90 +size 9280 diff --git a/screenshots/de/libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_de.png b/screenshots/de/libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_de.png index 2958d50ac6..448999910f 100644 --- a/screenshots/de/libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_de.png +++ b/screenshots/de/libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9494488876263418a4c86505482910776062277385924f69e1dcb468d474991 -size 25944 +oid sha256:09ea44484d7dbedf8c37888360df25910f6cf03eb80924f5018500ade17c53c6 +size 25978 diff --git a/screenshots/de/libraries.designsystem.components.dialogs_RetryDialog_Day_0_de.png b/screenshots/de/libraries.designsystem.components.dialogs_RetryDialog_Day_0_de.png index ae23a0e725..78a751b5c4 100644 --- a/screenshots/de/libraries.designsystem.components.dialogs_RetryDialog_Day_0_de.png +++ b/screenshots/de/libraries.designsystem.components.dialogs_RetryDialog_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46767b660cc867c2a3a264c35ff8d1b91593ee0b888dcf4a40c67361c36b5a74 -size 15358 +oid sha256:dd9c051d47ffb1b91684e919796363b8d206fd2f2ab715a95ebb0e8e7e6000ca +size 15348 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_2_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_2_de.png index 4b6d14cdb7..39dedcbc2a 100644 --- a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_2_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c88b10eeb0b787624d12e653d4b7037cdc42b90a91c40ea23ab7b661af03625 -size 45999 +oid sha256:3d6bc0b609f19136a6bdf9752d399047aac63f26e88bea363d823b5273f1657d +size 45992 diff --git a/screenshots/de/libraries.permissions.api_PermissionsView_Day_0_de.png b/screenshots/de/libraries.permissions.api_PermissionsView_Day_0_de.png index 0da1cc8f31..60c2b48abf 100644 --- a/screenshots/de/libraries.permissions.api_PermissionsView_Day_0_de.png +++ b/screenshots/de/libraries.permissions.api_PermissionsView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae922c3c9d531b7efc833804397263c0ab182288cd1f712a34cb6bb99f63d6c6 -size 30865 +oid sha256:206efed2c6d28aab43b1588113335574e671a388e948d8de9a0ae63c0372c06a +size 30922 diff --git a/screenshots/de/libraries.permissions.api_PermissionsView_Day_1_de.png b/screenshots/de/libraries.permissions.api_PermissionsView_Day_1_de.png index 53296f56b0..e874e82876 100644 --- a/screenshots/de/libraries.permissions.api_PermissionsView_Day_1_de.png +++ b/screenshots/de/libraries.permissions.api_PermissionsView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3aedcb2b94763b33f5b360655276af85913636850ce1afa43b22037b43475258 -size 30795 +oid sha256:284912820f3cc73c1067d45580f7bc07c743f2a21ab96842609f4b57ccc14fc6 +size 30861 diff --git a/screenshots/de/libraries.permissions.api_PermissionsView_Day_2_de.png b/screenshots/de/libraries.permissions.api_PermissionsView_Day_2_de.png index a6acef7c27..28037f69cb 100644 --- a/screenshots/de/libraries.permissions.api_PermissionsView_Day_2_de.png +++ b/screenshots/de/libraries.permissions.api_PermissionsView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca3b5c81ccb5a13945fe584f98746313d3050468aa9bf46f7bbdb44266996374 -size 29623 +oid sha256:7d977bd436da02de2a76a0037e0704ba9878919b53dc502d963d6b6b8c9a9237 +size 29671 diff --git a/screenshots/de/libraries.permissions.api_PermissionsView_Day_3_de.png b/screenshots/de/libraries.permissions.api_PermissionsView_Day_3_de.png index b3041ab22d..63e70d9fe8 100644 --- a/screenshots/de/libraries.permissions.api_PermissionsView_Day_3_de.png +++ b/screenshots/de/libraries.permissions.api_PermissionsView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a31fbffb7529b127443b4a52651cae6b0a525b2ec2ded82eb19c390eae4953cf -size 24256 +oid sha256:f7390a48f7e11f4e907c89beedb1250c43312c63cc9ad54b2f9983e5f3fcb675 +size 24176 diff --git a/screenshots/de/services.apperror.impl_AppErrorView_Day_0_de.png b/screenshots/de/services.apperror.impl_AppErrorView_Day_0_de.png index 9116a57f72..f446c5ac38 100644 --- a/screenshots/de/services.apperror.impl_AppErrorView_Day_0_de.png +++ b/screenshots/de/services.apperror.impl_AppErrorView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26388ccf8c8d78a991bd46f39983536be27a1093d354436cfd3df466a414496b -size 19558 +oid sha256:43272bd940257366c0ac035787b1603fa5bd3903e67760a262c289a4e8ffb4e3 +size 19531 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 8e59d76a06..d4e0ce58b9 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,77 +1,77 @@ // 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",20343,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20350,], ["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_0_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20343,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20343,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20343,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20343,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20343,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20343,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20343,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20343,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20343,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20343,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20343,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20350,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20350,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20350,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20350,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20350,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20350,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20350,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20350,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20350,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20350,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20350,], ["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,], ["features.messages.impl.actionlist_ActionListViewContent_Day_0_en","features.messages.impl.actionlist_ActionListViewContent_Night_0_en",0,], -["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20343,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20343,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20350,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20350,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20350,], ["features.messages.impl.actionlist_ActionListViewContent_Day_1_en","features.messages.impl.actionlist_ActionListViewContent_Night_1_en",0,], -["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20343,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20343,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20343,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20343,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20343,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20343,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20343,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20343,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20343,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20343,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20343,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20346,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20343,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20343,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20343,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20343,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20343,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20343,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20343,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20343,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20343,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20350,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20350,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20350,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20350,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20350,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20350,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20350,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20350,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20350,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20350,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20350,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20350,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20350,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20350,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20350,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20350,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20350,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20350,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20350,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20350,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20343,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20350,], ["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",20343,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20350,], ["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",20343,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20350,], ["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",20343,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20350,], ["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",20343,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20350,], ["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,], @@ -81,19 +81,19 @@ export const screenshots = [ ["libraries.matrix.ui.components_AttachmentThumbnail_Day_6_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_6_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_7_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_7_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_8_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_8_en",0,], -["features.messages.impl.attachments.preview_AttachmentsView_0_en","",20343,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",20343,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",20343,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",20343,], -["features.messages.impl.attachments.preview_AttachmentsView_4_en","",20343,], -["features.messages.impl.attachments.preview_AttachmentsView_5_en","",20343,], -["features.messages.impl.attachments.preview_AttachmentsView_6_en","",20343,], -["features.messages.impl.attachments.preview_AttachmentsView_7_en","",20343,], -["features.messages.impl.attachments.preview_AttachmentsView_8_en","",20343,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",20350,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",20350,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",20350,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",20350,], +["features.messages.impl.attachments.preview_AttachmentsView_4_en","",20350,], +["features.messages.impl.attachments.preview_AttachmentsView_5_en","",20350,], +["features.messages.impl.attachments.preview_AttachmentsView_6_en","",20350,], +["features.messages.impl.attachments.preview_AttachmentsView_7_en","",20350,], +["features.messages.impl.attachments.preview_AttachmentsView_8_en","",20350,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en",0,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en",0,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20343,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20350,], ["libraries.designsystem.components.avatar.internal_AvatarCluster_Avatars_en","",0,], ["libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Day_0_en","libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Night_0_en",0,], ["libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Day_1_en","libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Night_1_en",0,], @@ -225,150 +225,152 @@ export const screenshots = [ ["libraries.designsystem.modifiers_BackgroundVerticalGradientEnterprise_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradientEnterprise_Night_0_en",0,], ["libraries.designsystem.modifiers_BackgroundVerticalGradient_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradient_Night_0_en",0,], ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], -["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20343,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20350,], ["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",20343,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20343,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20343,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20343,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20343,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20343,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20343,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20350,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20350,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20350,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20350,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20350,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20350,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20350,], ["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",20343,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",20343,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",20343,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",20343,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",20343,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",20350,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",20350,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",20350,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",20350,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",20350,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_0_en","features.messages.impl.timeline.components_CallMenuItem_Night_0_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_1_en","features.messages.impl.timeline.components_CallMenuItem_Night_1_en",0,], -["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",20343,], -["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20343,], +["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",20350,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20350,], ["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_5_en","features.messages.impl.timeline.components_CallMenuItem_Night_5_en",0,], ["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,], -["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20343,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20343,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20343,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20343,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20343,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_0_en","features.changeroommemberroles.impl_ChangeRolesView_Night_0_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_10_en","features.changeroommemberroles.impl_ChangeRolesView_Night_10_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_11_en","features.changeroommemberroles.impl_ChangeRolesView_Night_11_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_12_en","features.changeroommemberroles.impl_ChangeRolesView_Night_12_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_1_en","features.changeroommemberroles.impl_ChangeRolesView_Night_1_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_2_en","features.changeroommemberroles.impl_ChangeRolesView_Night_2_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_3_en","features.changeroommemberroles.impl_ChangeRolesView_Night_3_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_4_en","features.changeroommemberroles.impl_ChangeRolesView_Night_4_en",20343,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20350,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20350,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20350,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20350,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20350,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_0_en","features.changeroommemberroles.impl_ChangeRolesView_Night_0_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_10_en","features.changeroommemberroles.impl_ChangeRolesView_Night_10_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_11_en","features.changeroommemberroles.impl_ChangeRolesView_Night_11_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_12_en","features.changeroommemberroles.impl_ChangeRolesView_Night_12_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_1_en","features.changeroommemberroles.impl_ChangeRolesView_Night_1_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_2_en","features.changeroommemberroles.impl_ChangeRolesView_Night_2_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_3_en","features.changeroommemberroles.impl_ChangeRolesView_Night_3_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_4_en","features.changeroommemberroles.impl_ChangeRolesView_Night_4_en",20350,], ["features.changeroommemberroles.impl_ChangeRolesView_Day_5_en","features.changeroommemberroles.impl_ChangeRolesView_Night_5_en",0,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_6_en","features.changeroommemberroles.impl_ChangeRolesView_Night_6_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_7_en","features.changeroommemberroles.impl_ChangeRolesView_Night_7_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_8_en","features.changeroommemberroles.impl_ChangeRolesView_Night_8_en",20343,], -["features.changeroommemberroles.impl_ChangeRolesView_Day_9_en","features.changeroommemberroles.impl_ChangeRolesView_Night_9_en",20343,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",20343,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",20343,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",20343,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",20343,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",20343,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",20343,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",20343,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_6_en","features.changeroommemberroles.impl_ChangeRolesView_Night_6_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_7_en","features.changeroommemberroles.impl_ChangeRolesView_Night_7_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_8_en","features.changeroommemberroles.impl_ChangeRolesView_Night_8_en",20350,], +["features.changeroommemberroles.impl_ChangeRolesView_Day_9_en","features.changeroommemberroles.impl_ChangeRolesView_Night_9_en",20350,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",20350,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",20350,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",20350,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",20350,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",20350,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",20350,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",20350,], ["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",20343,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20343,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20343,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20343,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20350,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20350,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20350,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20350,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20343,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20350,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20343,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20343,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20343,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20343,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20343,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20343,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20343,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20350,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20350,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20350,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20350,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20350,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20350,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20350,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20343,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20343,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20343,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20350,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20350,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20350,], ["libraries.textcomposer_ComposerModeView_Day_1_en","libraries.textcomposer_ComposerModeView_Night_1_en",0,], ["libraries.textcomposer_ComposerModeView_Day_2_en","libraries.textcomposer_ComposerModeView_Night_2_en",0,], ["libraries.textcomposer_ComposerModeView_Day_3_en","libraries.textcomposer_ComposerModeView_Night_3_en",0,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20343,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20343,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20343,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20343,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20343,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20343,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20350,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20350,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20350,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20350,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20350,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20350,], ["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,], ["libraries.designsystem.atomic.atoms_CounterAtom_Day_0_en","libraries.designsystem.atomic.atoms_CounterAtom_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20343,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20343,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20343,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20343,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20343,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20343,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20343,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20343,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20343,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20343,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20343,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20343,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20343,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20343,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20343,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20343,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20343,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20343,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20343,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20343,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20350,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20350,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20350,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20350,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20350,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20350,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20350,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20350,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20350,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20350,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20350,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20350,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20350,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20350,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20350,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20350,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20350,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20350,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20350,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20350,], ["libraries.mediaviewer.impl.gallery.ui_DateItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_DateItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_DateItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_DateItemView_Night_1_en",0,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20343,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20343,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20343,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20343,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20343,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20343,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20343,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20350,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20350,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20350,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20350,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20350,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20350,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20350,], ["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",20343,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20343,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20343,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20350,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20350,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20350,], ["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",20343,], -["features.home.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.home.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",20343,], -["features.home.impl.components_DefaultRoomListTopBar_Day_0_en","features.home.impl.components_DefaultRoomListTopBar_Night_0_en",20343,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20350,], +["features.home.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.home.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",20350,], +["features.home.impl.components_DefaultRoomListTopBar_Day_0_en","features.home.impl.components_DefaultRoomListTopBar_Night_0_en",20350,], ["features.licenses.impl.details_DependenciesDetailsView_Day_0_en","features.licenses.impl.details_DependenciesDetailsView_Night_0_en",0,], -["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20343,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20343,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20343,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20343,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20343,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20343,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20343,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20350,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20350,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20350,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20350,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20350,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20350,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20350,], ["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,], ["libraries.designsystem.theme.components_DialogWithTitleAndOkButton_Dialog_with_title_and_ok_button_Dialogs_en","",0,], ["libraries.designsystem.theme.components_DialogWithTitleIconAndOkButton_Dialog_with_title,_icon_and_ok_button_Dialogs_en","",0,], +["libraries.designsystem.theme.components_DialogWithVeryLongTitleAndIcon_Dialog_with_a_very_long_title_and_icon_Dialogs_en","",0,], +["libraries.designsystem.theme.components_DialogWithVeryLongTitle_Dialog_with_a_very_long_title_Dialogs_en","",0,], ["features.messages.impl.messagecomposer_DisabledComposerView_Day_0_en","features.messages.impl.messagecomposer_DisabledComposerView_Night_0_en",0,], ["libraries.designsystem.components.avatar_DmAvatarsRtl_Avatars_en","",0,], ["libraries.designsystem.components.avatar_DmAvatars_Avatars_en","",0,], @@ -376,18 +378,18 @@ 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",20343,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20343,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20343,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20343,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20343,], -["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_0_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_0_en",20343,], -["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_1_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_1_en",20343,], -["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_2_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_2_en",20343,], -["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_3_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_3_en",20343,], -["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_4_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_4_en",20343,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20343,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20343,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20350,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20350,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20350,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20350,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20350,], +["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_0_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_0_en",20350,], +["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_1_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_1_en",20350,], +["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_2_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_2_en",20350,], +["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_3_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_3_en",20350,], +["features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_4_en","features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Night_4_en",20350,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20350,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20350,], ["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,], @@ -398,13 +400,13 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20343,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20343,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20350,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20350,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_2_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_2_en",0,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_3_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_3_en",0,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20343,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20343,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20343,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20350,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20350,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20350,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.designsystem.components_ExpandableBottomSheetLayout_en","",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], @@ -423,41 +425,41 @@ 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",20343,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20343,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20343,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20350,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20350,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20350,], ["features.messages.impl.timeline.components_FocusedEventEnterprise_Day_0_en","features.messages.impl.timeline.components_FocusedEventEnterprise_Night_0_en",0,], ["features.messages.impl.timeline.components_FocusedEvent_Day_0_en","features.messages.impl.timeline.components_FocusedEvent_Night_0_en",0,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.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",20343,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20343,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",20350,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20350,], ["libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Night_0_en",0,], ["libraries.designsystem.components.button_GradientFloatingActionButton_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButton_Night_0_en",0,], ["features.messages.impl.timeline.components.group_GroupHeaderView_Day_0_en","features.messages.impl.timeline.components.group_GroupHeaderView_Night_0_en",0,], ["libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Day_0_en","libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Night_0_en",0,], ["libraries.designsystem.atomic.pages_HeaderFooterPage_Day_0_en","libraries.designsystem.atomic.pages_HeaderFooterPage_Night_0_en",0,], -["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20343,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20343,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20350,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20350,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20343,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20343,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20350,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20350,], ["features.home.impl_HomeView_Day_11_en","features.home.impl_HomeView_Night_11_en",0,], ["features.home.impl_HomeView_Day_12_en","features.home.impl_HomeView_Night_12_en",0,], -["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20343,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20343,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20343,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20343,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20343,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20343,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20343,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20343,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20343,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20343,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20343,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20343,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20350,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20350,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20350,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20350,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20350,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20350,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20350,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20350,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20350,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20350,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20350,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20350,], ["libraries.designsystem.theme.components_HorizontalDivider_Dividers_en","",0,], ["libraries.designsystem.ruler_HorizontalRuler_Day_0_en","libraries.designsystem.ruler_HorizontalRuler_Night_0_en",0,], ["libraries.designsystem.theme.components_IconButton_Buttons_en","",0,], @@ -476,8 +478,8 @@ export const screenshots = [ ["libraries.designsystem.icons_IconsCompound_Day_5_en","libraries.designsystem.icons_IconsCompound_Night_5_en",0,], ["libraries.designsystem.icons_IconsOther_Day_0_en","libraries.designsystem.icons_IconsOther_Night_0_en",0,], ["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_0_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_0_en",0,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20343,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20343,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20350,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20350,], ["libraries.mediaviewer.impl.gallery.ui_ImageItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_ImageItemView_Night_0_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_0_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_0_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_10_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_10_en",0,], @@ -485,97 +487,97 @@ 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",20343,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20350,], ["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",20343,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20350,], ["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",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20343,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20343,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20350,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20350,], ["features.networkmonitor.api.ui_Indicator_Day_0_en","features.networkmonitor.api.ui_Indicator_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], ["libraries.matrix.ui.media_InitialsAvatarBitmapGenerator_Day_0_en","libraries.matrix.ui.media_InitialsAvatarBitmapGenerator_Night_0_en",0,], -["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20343,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20343,], -["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20343,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20350,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20350,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20350,], ["features.invitepeople.impl_InvitePeopleView_Day_2_en","features.invitepeople.impl_InvitePeopleView_Night_2_en",0,], ["features.invitepeople.impl_InvitePeopleView_Day_3_en","features.invitepeople.impl_InvitePeopleView_Night_3_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20343,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20343,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20343,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20343,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20350,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20350,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20350,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20350,], ["features.invitepeople.impl_InvitePeopleView_Day_8_en","features.invitepeople.impl_InvitePeopleView_Night_8_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20346,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20343,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20343,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20343,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20343,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20343,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20343,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20343,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20350,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20350,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20350,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20350,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20350,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20350,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20350,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20350,], ["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",20343,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20343,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20343,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20343,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20343,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20343,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20343,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20343,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20343,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20343,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20343,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20350,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20350,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20350,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20350,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20350,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20350,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20350,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20350,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20350,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20350,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["features.leaveroom.impl_LeaveRoomView_Day_0_en","features.leaveroom.impl_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20343,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20343,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20343,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20343,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20343,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20343,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20343,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20350,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20350,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20350,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20350,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20350,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20350,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20350,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress_Indicators_en","",0,], ["features.messages.impl.link_LinkView_Day_0_en","features.messages.impl.link_LinkView_Night_0_en",0,], -["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20343,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20350,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ListDialog_Day_0_en","libraries.designsystem.components.dialogs_ListDialog_Night_0_en",0,], ["libraries.designsystem.theme.components_ListItemPrimaryActionWithIcon_List_item_-_Primary_action_&_Icon_List_items_en","",0,], @@ -630,36 +632,36 @@ 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",20343,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20343,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20343,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20343,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20350,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20350,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20350,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20350,], ["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",20343,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20343,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20343,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20343,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20343,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20343,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20343,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20343,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20343,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20343,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20343,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20343,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20343,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20343,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20343,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20343,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20343,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20343,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20343,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20343,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20343,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20343,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20343,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20350,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20350,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20350,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20350,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20350,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20350,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20350,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20350,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20350,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20350,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20350,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20350,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20350,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20350,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20350,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20350,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20350,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20350,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20350,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20350,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20350,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20350,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20350,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20343,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20350,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Night_0_en",0,], @@ -672,22 +674,22 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20343,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20343,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20350,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20350,], ["libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en",0,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20343,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20343,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20350,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20350,], ["libraries.mediaviewer.impl.local.image_MediaImageView_Day_0_en","libraries.mediaviewer.impl.local.image_MediaImageView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en",0,], @@ -695,14 +697,14 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20343,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20343,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20350,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20350,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20343,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20350,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20343,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20350,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -716,7 +718,7 @@ export const screenshots = [ ["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,], ["libraries.designsystem.theme.components.previews_Menu_Menus_en","",0,], ["features.messages.impl.messagecomposer_MessageComposerViewVoice_Day_0_en","features.messages.impl.messagecomposer_MessageComposerViewVoice_Night_0_en",0,], -["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20343,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20350,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_1_en","features.messages.impl.timeline.components_MessageEventBubble_Night_1_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_2_en","features.messages.impl.timeline.components_MessageEventBubble_Night_2_en",0,], @@ -725,7 +727,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessageEventBubble_Day_5_en","features.messages.impl.timeline.components_MessageEventBubble_Night_5_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_6_en","features.messages.impl.timeline.components_MessageEventBubble_Night_6_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,], -["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20343,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20350,], ["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,], @@ -733,27 +735,27 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_1_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_1_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20343,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20343,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20343,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20343,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20343,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20343,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",20343,], -["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",20343,], -["features.messages.impl_MessagesView_Day_14_en","features.messages.impl_MessagesView_Night_14_en",20343,], -["features.messages.impl_MessagesView_Day_15_en","features.messages.impl_MessagesView_Night_15_en",20343,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20343,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20343,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20343,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20343,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20343,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20343,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20343,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20343,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20343,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20350,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20350,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20350,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20350,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20350,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20350,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",20350,], +["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",20350,], +["features.messages.impl_MessagesView_Day_14_en","features.messages.impl_MessagesView_Night_14_en",20350,], +["features.messages.impl_MessagesView_Day_15_en","features.messages.impl_MessagesView_Night_15_en",20350,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20350,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20350,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20350,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20350,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20350,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20350,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20350,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20350,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20350,], ["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",20343,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20350,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom_Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom_Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -763,109 +765,109 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20343,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20343,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20343,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20350,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20350,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20350,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20343,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20343,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20343,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20343,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20343,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20343,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20343,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20350,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20350,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20350,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20350,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20350,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20350,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20350,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], -["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20343,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20350,], ["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_12_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_12_en",0,], ["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_13_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_13_en",0,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20343,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20343,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20350,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20350,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonSmall_Buttons_en","",0,], -["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20343,], -["features.changeroommemberroles.impl_PendingMemberRowWithLongName_Day_0_en","features.changeroommemberroles.impl_PendingMemberRowWithLongName_Night_0_en",20343,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20343,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20343,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20343,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20343,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20350,], +["features.changeroommemberroles.impl_PendingMemberRowWithLongName_Day_0_en","features.changeroommemberroles.impl_PendingMemberRowWithLongName_Night_0_en",20350,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20350,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20350,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20350,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20350,], ["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",20343,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20343,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20343,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20350,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20350,], ["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20343,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20343,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20343,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20343,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20343,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20343,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20343,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20343,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20343,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20343,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20343,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20343,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20343,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20343,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20350,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20350,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20350,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20350,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20350,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20350,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20350,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20350,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20350,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20350,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20350,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20350,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20350,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20350,], ["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",20343,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20343,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20343,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20343,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20343,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20350,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20350,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20350,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20350,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20350,], ["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",20343,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20343,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20343,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20343,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20343,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20343,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20343,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20343,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20343,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20343,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20343,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20350,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20350,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20350,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20350,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20350,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20350,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20350,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20350,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20350,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20350,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20350,], ["features.poll.api.pollcontent_PollTitleView_Day_0_en","features.poll.api.pollcontent_PollTitleView_Night_0_en",0,], ["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,], @@ -879,206 +881,206 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceRow_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20343,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20343,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20343,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20343,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20350,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20350,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20350,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20350,], ["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","",20343,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20346,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20350,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20350,], ["libraries.designsystem.components_ProgressDialogWithTextAndContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithTextAndContent_Night_0_en",0,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20343,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20343,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20343,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20343,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20343,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20343,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20343,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20343,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20343,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20343,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20343,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20343,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20343,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20343,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20343,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20343,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20343,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20343,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20343,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20343,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20343,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20343,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20343,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20343,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20343,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20343,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20350,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20350,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20350,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20350,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20350,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20350,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20350,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20350,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20350,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20350,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20350,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20350,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20350,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20350,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20350,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20350,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20350,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20350,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20350,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20350,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20350,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20350,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20350,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20350,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20350,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20350,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20343,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20343,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20350,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20350,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], ["features.messages.impl.timeline.components.reactionsummary_ReactionSummaryViewContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_ReactionSummaryViewContent_Night_0_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20343,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20343,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20343,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20343,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20343,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20343,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20343,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20350,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20350,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20350,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20350,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20350,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20350,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20350,], ["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",20343,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20343,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20343,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20343,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20343,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20343,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20343,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20343,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20343,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20343,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20343,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20343,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20343,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20343,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20343,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20343,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20343,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20350,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20350,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20350,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20350,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20350,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20350,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20350,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20350,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20350,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20350,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20350,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20350,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20350,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20350,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20350,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20350,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20350,], ["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_0_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_0_en",0,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20343,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20343,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20343,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20343,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",20343,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",20343,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",20343,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",20343,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",20343,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",20343,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",20343,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",20343,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_8_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_8_en",20343,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20350,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20350,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20350,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20350,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",20350,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",20350,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",20350,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",20350,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",20350,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",20350,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",20350,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",20350,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_8_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_8_en",20350,], ["libraries.matrix.ui.room.address_RoomAddressField_Day_0_en","libraries.matrix.ui.room.address_RoomAddressField_Night_0_en",0,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20343,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20343,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20343,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20343,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",20343,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",20343,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",20343,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",20343,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",20343,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",20343,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",20343,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",20343,], -["features.roomdetails.impl_RoomDetails_0_en","",20343,], -["features.roomdetails.impl_RoomDetails_10_en","",20343,], -["features.roomdetails.impl_RoomDetails_11_en","",20343,], -["features.roomdetails.impl_RoomDetails_12_en","",20343,], -["features.roomdetails.impl_RoomDetails_13_en","",20343,], -["features.roomdetails.impl_RoomDetails_14_en","",20343,], -["features.roomdetails.impl_RoomDetails_15_en","",20343,], -["features.roomdetails.impl_RoomDetails_16_en","",20343,], -["features.roomdetails.impl_RoomDetails_17_en","",20343,], -["features.roomdetails.impl_RoomDetails_18_en","",20343,], -["features.roomdetails.impl_RoomDetails_19_en","",20343,], -["features.roomdetails.impl_RoomDetails_1_en","",20343,], -["features.roomdetails.impl_RoomDetails_2_en","",20343,], -["features.roomdetails.impl_RoomDetails_3_en","",20343,], -["features.roomdetails.impl_RoomDetails_4_en","",20343,], -["features.roomdetails.impl_RoomDetails_5_en","",20343,], -["features.roomdetails.impl_RoomDetails_6_en","",20343,], -["features.roomdetails.impl_RoomDetails_7_en","",20343,], -["features.roomdetails.impl_RoomDetails_8_en","",20343,], -["features.roomdetails.impl_RoomDetails_9_en","",20343,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20343,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20343,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20343,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20343,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20343,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20343,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20346,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20343,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20343,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20350,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20350,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20350,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20350,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",20350,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",20350,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",20350,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",20350,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",20350,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",20350,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",20350,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",20350,], +["features.roomdetails.impl_RoomDetails_0_en","",20350,], +["features.roomdetails.impl_RoomDetails_10_en","",20350,], +["features.roomdetails.impl_RoomDetails_11_en","",20350,], +["features.roomdetails.impl_RoomDetails_12_en","",20350,], +["features.roomdetails.impl_RoomDetails_13_en","",20350,], +["features.roomdetails.impl_RoomDetails_14_en","",20350,], +["features.roomdetails.impl_RoomDetails_15_en","",20350,], +["features.roomdetails.impl_RoomDetails_16_en","",20350,], +["features.roomdetails.impl_RoomDetails_17_en","",20350,], +["features.roomdetails.impl_RoomDetails_18_en","",20350,], +["features.roomdetails.impl_RoomDetails_19_en","",20350,], +["features.roomdetails.impl_RoomDetails_1_en","",20350,], +["features.roomdetails.impl_RoomDetails_2_en","",20350,], +["features.roomdetails.impl_RoomDetails_3_en","",20350,], +["features.roomdetails.impl_RoomDetails_4_en","",20350,], +["features.roomdetails.impl_RoomDetails_5_en","",20350,], +["features.roomdetails.impl_RoomDetails_6_en","",20350,], +["features.roomdetails.impl_RoomDetails_7_en","",20350,], +["features.roomdetails.impl_RoomDetails_8_en","",20350,], +["features.roomdetails.impl_RoomDetails_9_en","",20350,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20350,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20350,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20350,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20350,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20350,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20350,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20350,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20350,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20350,], ["features.home.impl.components_RoomListContentView_Day_2_en","features.home.impl.components_RoomListContentView_Night_2_en",0,], -["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20343,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20343,], -["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20343,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20343,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20343,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20343,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20343,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20343,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20350,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20350,], +["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20350,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20350,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20350,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20350,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20350,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20350,], ["features.home.impl.search_RoomListSearchContent_Day_0_en","features.home.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20343,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",20343,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",20343,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",20343,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20343,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20343,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20343,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20343,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20343,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20343,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20350,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",20350,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",20350,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",20350,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20350,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20350,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20350,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20350,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20350,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20350,], ["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",20343,], -["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",20343,], -["features.roomdetails.impl.members_RoomMemberListView_Day_9_en","features.roomdetails.impl.members_RoomMemberListView_Night_9_en",20343,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20343,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20343,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20343,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20343,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20343,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20343,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20343,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20343,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20343,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20343,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20343,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20343,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20343,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20343,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20343,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20343,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20343,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20343,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20343,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20343,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20343,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20343,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",20350,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",20350,], +["features.roomdetails.impl.members_RoomMemberListView_Day_9_en","features.roomdetails.impl.members_RoomMemberListView_Night_9_en",20350,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20350,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20350,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20350,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20350,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20350,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20350,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20350,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20350,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20350,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20350,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20350,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20350,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20350,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20350,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20350,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20350,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20350,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20350,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20350,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20350,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20350,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20350,], ["features.home.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.home.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_0_en","features.home.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_10_en","features.home.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -1101,13 +1103,13 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20343,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20343,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20343,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20343,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20343,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20343,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20343,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20350,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20350,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20350,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20350,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20350,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20350,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20350,], ["features.home.impl.components_RoomSummaryRow_Day_3_en","features.home.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_4_en","features.home.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_5_en","features.home.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -1115,80 +1117,80 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_7_en","features.home.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_8_en","features.home.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_9_en","features.home.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20343,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20343,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20343,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20350,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20350,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20350,], ["appicon.enterprise_RoundIcon_en","",0,], ["appicon.element_RoundIcon_en","",0,], ["libraries.designsystem.atomic.atoms_RoundedIconAtom_Day_0_en","libraries.designsystem.atomic.atoms_RoundedIconAtom_Night_0_en",0,], -["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20343,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20343,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20343,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20350,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20350,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20350,], ["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","",20343,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20350,], ["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.startchat.impl.components_SearchMultipleUsersResultItem_en","",20343,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20343,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20343,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20343,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20343,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20343,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20343,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20343,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20343,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20343,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20343,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20343,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_0_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_1_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_2_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_3_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_4_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_5_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_6_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_8_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_0_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_1_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_2_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_3_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_4_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_5_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_6_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_en","",20343,], -["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_8_en","",20343,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20350,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20350,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20350,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20350,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20350,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20350,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20350,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20350,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20350,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20350,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20350,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20350,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_0_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_1_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_2_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_3_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_4_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_5_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_6_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_8_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_0_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_1_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_2_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_3_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_4_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_5_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_6_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_en","",20350,], +["features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_8_en","",20350,], ["libraries.designsystem.atomic.atoms_SelectedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_SelectedIndicatorAtom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoomRtl_Day_0_en","libraries.matrix.ui.components_SelectedRoomRtl_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoomRtl_Day_1_en","libraries.matrix.ui.components_SelectedRoomRtl_Night_1_en",0,], @@ -1202,11 +1204,11 @@ export const screenshots = [ ["libraries.matrix.ui.components_SelectedUser_Day_1_en","libraries.matrix.ui.components_SelectedUser_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",20343,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",20343,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",20343,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",20343,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",20343,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",20350,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",20350,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",20350,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",20350,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",20350,], ["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,], @@ -1216,27 +1218,27 @@ export const screenshots = [ ["libraries.matrix.ui.messages.sender_SenderName_Day_6_en","libraries.matrix.ui.messages.sender_SenderName_Night_6_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_7_en","libraries.matrix.ui.messages.sender_SenderName_Night_7_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_8_en","libraries.matrix.ui.messages.sender_SenderName_Night_8_en",0,], -["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20343,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20343,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20343,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20343,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20343,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20343,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20343,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20343,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20350,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20350,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20350,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20350,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20350,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20350,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20350,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20350,], ["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",20343,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20343,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20343,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20343,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20343,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20343,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20343,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20343,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20343,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20343,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20350,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20350,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20350,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20350,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20350,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20350,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20350,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20350,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20350,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20350,], ["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,], @@ -1245,86 +1247,86 @@ 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",20343,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20350,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20343,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20343,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20343,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20350,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20350,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20350,], ["libraries.matrix.ui.components_SpaceMembersViewNoHeroes_Day_0_en","libraries.matrix.ui.components_SpaceMembersViewNoHeroes_Night_0_en",0,], ["libraries.matrix.ui.components_SpaceMembersView_Day_0_en","libraries.matrix.ui.components_SpaceMembersView_Night_0_en",0,], ["features.space.impl_SpaceView_Day_0_en","features.space.impl_SpaceView_Night_0_en",0,], ["features.space.impl_SpaceView_Day_1_en","features.space.impl_SpaceView_Night_1_en",0,], -["features.space.impl_SpaceView_Day_2_en","features.space.impl_SpaceView_Night_2_en",20346,], -["features.space.impl_SpaceView_Day_3_en","features.space.impl_SpaceView_Night_3_en",20346,], +["features.space.impl_SpaceView_Day_2_en","features.space.impl_SpaceView_Night_2_en",20350,], +["features.space.impl_SpaceView_Day_3_en","features.space.impl_SpaceView_Night_3_en",20350,], ["libraries.designsystem.modifiers_SquareSizeModifierInsideSquare_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], -["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20343,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20343,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20343,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20343,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20343,], -["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20343,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20343,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20350,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20350,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20350,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20350,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20350,], +["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20350,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20350,], ["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",20343,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20350,], ["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",20343,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20350,], ["libraries.designsystem.components.avatar.internal_TextAvatar_Avatars_en","",0,], ["libraries.designsystem.theme.components_TextButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonLarge_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonSmall_Buttons_en","",0,], -["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20343,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20343,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20343,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20343,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20343,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20343,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20343,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20343,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20343,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20343,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20343,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20343,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20343,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20343,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20343,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20350,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20350,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20350,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20350,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20350,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20350,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20350,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20350,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20350,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20350,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20350,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20350,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20350,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20350,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20350,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], -["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20343,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20343,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20350,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20350,], ["libraries.designsystem.components.list_TextFieldListItemEmpty_Text_field_List_item_-_empty_List_items_en","",0,], ["libraries.designsystem.components.list_TextFieldListItemTextFieldValue_Text_field_List_item_-_textfieldvalue_List_items_en","",0,], ["libraries.designsystem.components.list_TextFieldListItem_Text_field_List_item_-_text_List_items_en","",0,], @@ -1336,14 +1338,14 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.txt_TextFileContentView_Day_3_en","libraries.mediaviewer.impl.local.txt_TextFileContentView_Night_3_en",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20343,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20343,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20343,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20350,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20350,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20350,], ["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",20343,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20343,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20350,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20350,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_7_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_7_en",0,], @@ -1353,18 +1355,18 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en",0,], -["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20343,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20350,], ["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",20343,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20350,], ["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,], @@ -1372,18 +1374,18 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20343,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20343,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20350,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20350,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_6_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20343,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20343,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20343,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20350,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20350,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20350,], ["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",20343,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20343,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20350,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20350,], ["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,], @@ -1392,41 +1394,41 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20343,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20350,], ["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",20343,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20350,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20343,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20350,], ["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","",20343,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20350,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en",0,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20343,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20343,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20350,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20350,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemInformativeView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemInformativeView_Night_0_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20350,], ["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",20343,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20343,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20350,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20350,], ["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",20343,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20343,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20350,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20350,], ["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",20343,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20350,], ["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,], @@ -1435,8 +1437,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",20343,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20350,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20350,], ["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,], @@ -1451,8 +1453,8 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_4_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_5_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20343,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20343,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20350,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20350,], ["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,], @@ -1475,85 +1477,85 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_9_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en",0,], -["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20343,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20343,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20350,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20350,], ["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",20343,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20343,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20343,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20343,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20343,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20343,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20343,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20343,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20350,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20350,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20350,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20350,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20350,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20350,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20350,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20350,], ["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",20343,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20350,], ["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",20343,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20350,], ["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",20343,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",20350,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.components.avatar.internal_TombstonedRoomAvatar_Avatars_en","",0,], ["libraries.designsystem.theme.components_TopAppBarStr_App_Bars_en","",0,], ["libraries.designsystem.theme.components_TopAppBar_App_Bars_en","",0,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20343,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20343,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20343,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20343,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20343,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20343,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20343,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20343,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20350,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20350,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20350,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20350,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20350,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20350,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20350,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20350,], ["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",20343,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20343,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20343,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20343,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20343,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20343,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20350,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20350,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20350,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20350,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20350,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20350,], ["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","",20343,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20350,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar.internal_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar.internal_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20343,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20343,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20343,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20343,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20350,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20350,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20350,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20350,], ["features.startchat.impl.components_UserListView_Day_3_en","features.startchat.impl.components_UserListView_Night_3_en",0,], ["features.startchat.impl.components_UserListView_Day_4_en","features.startchat.impl.components_UserListView_Night_4_en",0,], ["features.startchat.impl.components_UserListView_Day_5_en","features.startchat.impl.components_UserListView_Night_5_en",0,], ["features.startchat.impl.components_UserListView_Day_6_en","features.startchat.impl.components_UserListView_Night_6_en",0,], -["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20343,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20350,], ["features.startchat.impl.components_UserListView_Day_8_en","features.startchat.impl.components_UserListView_Night_8_en",0,], -["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20343,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20350,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20343,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20343,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20343,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20343,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20343,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20343,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20343,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20343,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20343,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20343,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20343,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20343,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20350,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20350,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20350,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20350,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20350,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20350,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20350,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20350,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20350,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20350,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20350,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20350,], ["features.verifysession.impl.ui_VerificationUserProfileContent_Day_0_en","features.verifysession.impl.ui_VerificationUserProfileContent_Night_0_en",0,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VideoItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_VideoItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VideoItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_VideoItemView_Night_1_en",0,], -["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20343,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20343,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20350,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20350,], ["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_2_en","features.viewfolder.impl.file_ViewFileView_Night_2_en",0,], -["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20343,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20350,], ["features.viewfolder.impl.file_ViewFileView_Day_4_en","features.viewfolder.impl.file_ViewFileView_Night_4_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_5_en","features.viewfolder.impl.file_ViewFileView_Night_5_en",0,], ["features.viewfolder.impl.folder_ViewFolderView_Day_0_en","features.viewfolder.impl.folder_ViewFolderView_Night_0_en",0,], From ef8bf0619a0ef92df6eb0017afa3a1e84021d8df Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Sep 2025 14:59:43 +0200 Subject: [PATCH 115/145] Code cleanup --- .../joinroom/impl/JoinRoomPresenter.kt | 10 -------- .../joinroom/impl/JoinRoomStateProvider.kt | 2 +- .../features/joinroom/impl/JoinRoomView.kt | 24 +------------------ .../matrix/impl/spaces/RustSpaceRoomList.kt | 1 - .../matrix/impl/spaces/SpaceRoomCache.kt | 1 - .../matrix/ui/components/SpaceRoomItemView.kt | 2 +- 6 files changed, 3 insertions(+), 37 deletions(-) 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 e8e891397c..74ab8151c3 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 @@ -42,7 +42,6 @@ import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.matrix.api.exception.ErrorKind import io.element.android.libraries.matrix.api.room.CurrentUserMembership -import io.element.android.libraries.matrix.api.room.NotJoinedRoom import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipDetails import io.element.android.libraries.matrix.api.room.RoomType @@ -220,15 +219,6 @@ class JoinRoomPresenter( } } - private suspend fun getRoomPreviewIfKnown(membership: CurrentUserMembership?): NotJoinedRoom? { - return when (membership) { - CurrentUserMembership.INVITED, - CurrentUserMembership.KNOCKED, - CurrentUserMembership.BANNED -> matrixClient.getRoomPreview(roomIdOrAlias, serverNames).getOrNull() - else -> null - } - } - private fun CoroutineScope.knockRoom(knockAction: MutableState>, message: String) = launch { knockAction.runUpdatingState { knockRoom(roomIdOrAlias, message, serverNames) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 244cc0579d..404b219dc9 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -165,7 +165,7 @@ fun aLoadedContentState( roomAvatarUrl: String? = null, joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown, childrenCount: Int? = null, - joinRule : JoinRule? = null, + joinRule: JoinRule? = null, heroes: List = emptyList() ) = ContentState.Loaded( roomId = roomId, diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index af4665e5da..807d476a99 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -366,28 +366,6 @@ private fun JoinRestrictedFooter( } } -@Composable -private fun UnsupportedSpaceFooter( - applicationName: String, - onGoBack: () -> Unit, - modifier: Modifier = Modifier, -) { - Column(modifier = modifier) { - Announcement( - title = stringResource(R.string.screen_join_room_space_not_supported_title), - description = stringResource(R.string.screen_join_room_space_not_supported_description, applicationName), - type = AnnouncementType.Informative(), - ) - Spacer(Modifier.height(24.dp)) - Button( - text = stringResource(CommonStrings.action_ok), - onClick = onGoBack, - modifier = Modifier.fillMaxWidth(), - size = ButtonSize.Large, - ) - } -} - @Composable private fun JoinRoomContent( roomIdOrAlias: RoomIdOrAlias, @@ -498,7 +476,7 @@ private fun UnknownRoomContent( modifier = modifier, avatar = { Box( - modifier = modifier + modifier = Modifier .size(AvatarSize.RoomPreviewHeader.dp) .background( color = ElementTheme.colors.placeholderBackground, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt index 7e6a9f6afa..1a940bd2f0 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomList.kt @@ -13,7 +13,6 @@ import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.api.spaces.SpaceRoomList import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt index f9d45e5ea6..c8f55f1db6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomCache.kt @@ -10,7 +10,6 @@ package io.element.android.libraries.matrix.impl.spaces import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt index 23baf476c0..e599b75cab 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt @@ -144,7 +144,7 @@ private fun NameAndIndicatorRow( Text( modifier = Modifier.weight(1f), style = ElementTheme.typography.fontBodyLgMedium, - text = name ?: stringResource(id = if(isSpace) CommonStrings.common_no_space_name else CommonStrings.common_no_room_name), + text = name ?: stringResource(id = if (isSpace) CommonStrings.common_no_space_name else CommonStrings.common_no_room_name), fontStyle = FontStyle.Italic.takeIf { name == null }, color = ElementTheme.colors.textPrimary, maxLines = 1, From 07660106df71e1aef5f48cd8a4d89ea960fc4177 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Sep 2025 15:08:14 +0200 Subject: [PATCH 116/145] Fix existing tests --- .../joinroom/impl/JoinRoomPresenterTest.kt | 206 ++++++++++++++---- .../joinroom/impl/JoinRoomViewTest.kt | 16 -- 2 files changed, 159 insertions(+), 63 deletions(-) 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 d636e9fb34..ee4b2625fd 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 @@ -28,7 +28,6 @@ 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.exception.ClientException import io.element.android.libraries.matrix.api.exception.ErrorKind @@ -50,6 +49,8 @@ import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.libraries.matrix.test.room.aRoomPreview import io.element.android.libraries.matrix.test.room.aRoomPreviewInfo import io.element.android.libraries.matrix.test.room.join.FakeJoinRoom +import io.element.android.libraries.matrix.test.spaces.FakeSpaceRoomList +import io.element.android.libraries.matrix.test.spaces.FakeSpaceService import io.element.android.libraries.matrix.ui.model.InviteSender import io.element.android.libraries.matrix.ui.model.toInviteSender import io.element.android.tests.testutils.WarmUpRule @@ -90,6 +91,9 @@ class JoinRoomPresenterTest { val roomInfo = aRoomInfo() val matrixClient = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ).apply { getRoomInfoFlowLambda = { _ -> flowOf(Optional.of(roomInfo)) @@ -118,6 +122,9 @@ class JoinRoomPresenterTest { val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED) val matrixClient = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ).apply { getRoomInfoFlowLambda = { _ -> flowOf(Optional.of(roomInfo)) @@ -142,7 +149,7 @@ class JoinRoomPresenterTest { @Test fun `present - when room is invited then join authorization is equal to invited, an inviter is provided`() = runTest { - val inviter = aRoomMember(userId = UserId("@bob:example.com"), displayName = "Bob") + val inviter = aRoomMember(userId = A_USER_ID_2, displayName = "Bob") val expectedInviteSender = inviter.toInviteSender() val roomInfo = aRoomInfo( currentUserMembership = CurrentUserMembership.INVITED, @@ -151,7 +158,21 @@ class JoinRoomPresenterTest { ) val inviteData = roomInfo.toInviteData() val matrixClient = FakeMatrixClient( - getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) }, + getNotJoinedRoomResult = { _, _ -> + Result.success( + aRoomPreview( + info = aRoomPreviewInfo( + numberOfJoinedMembers = 5, + ), + roomMembershipDetails = { + Result.success(aRoomMembershipDetails()) + }, + ) + ) + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ).apply { getRoomInfoFlowLambda = { _ -> flowOf(Optional.of(roomInfo)) @@ -182,10 +203,16 @@ class JoinRoomPresenterTest { aRoomPreview( info = aRoomPreviewInfo( numberOfJoinedMembers = 10, - ) + ), + roomMembershipDetails = { + Result.success(aRoomMembershipDetails()) + }, ) ) }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ).apply { getRoomInfoFlowLambda = { _ -> flowOf(Optional.of(roomInfo)) @@ -209,7 +236,11 @@ class JoinRoomPresenterTest { anAcceptDeclineInviteState(eventSink = eventSinkRecorder) } val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED) - val matrixClient = FakeMatrixClient().apply { + val matrixClient = FakeMatrixClient( + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), + ).apply { getRoomInfoFlowLambda = { _ -> flowOf(Optional.of(roomInfo)) } @@ -244,6 +275,9 @@ class JoinRoomPresenterTest { } val matrixClient = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = matrixClient, @@ -272,6 +306,9 @@ class JoinRoomPresenterTest { fun `present - when room is joined with error, it is possible to clear the error`() = runTest { val matrixClient = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = matrixClient, @@ -334,16 +371,14 @@ class JoinRoomPresenterTest { currentUserMembership = CurrentUserMembership.BANNED, ), roomMembershipDetails = { - Result.success( - RoomMembershipDetails( - currentUserMember = aRoomMember(userId = A_USER_ID, displayName = "Alice"), - senderMember = aRoomMember(userId = A_USER_ID_2, displayName = "Bob"), - ) - ) + Result.success(aRoomMembershipDetails()) } ) ) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ).apply { getRoomInfoFlowLambda = { _ -> flowOf(Optional.of(roomInfo)) @@ -371,6 +406,9 @@ class JoinRoomPresenterTest { val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.LEFT, joinRule = JoinRule.Public) val matrixClient = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ).apply { getRoomInfoFlowLambda = { _ -> flowOf(Optional.of(roomInfo)) @@ -392,6 +430,9 @@ class JoinRoomPresenterTest { val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.LEFT, joinRule = null) val matrixClient = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ).apply { getRoomInfoFlowLambda = { _ -> flowOf(Optional.of(roomInfo)) @@ -497,6 +538,9 @@ class JoinRoomPresenterTest { val fakeKnockRoom = FakeKnockRoom(knockRoomSuccess) val matrixClient = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = matrixClient, @@ -542,6 +586,9 @@ class JoinRoomPresenterTest { val cancelKnockRoom = FakeCancelKnockRoom(cancelKnockRoomSuccess) val matrixClient = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = matrixClient, @@ -586,6 +633,9 @@ class JoinRoomPresenterTest { val fakeForgetRoom = FakeForgetRoom(forgetRoomSuccess) val matrixClient = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = matrixClient, @@ -634,10 +684,16 @@ class JoinRoomPresenterTest { isHistoryWorldReadable = false, joinRule = JoinRule.Public, currentUserMembership = null, - ) + ), + roomMembershipDetails = { + Result.success(aRoomMembershipDetails()) + }, ) ) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -684,16 +740,14 @@ class JoinRoomPresenterTest { currentUserMembership = CurrentUserMembership.INVITED, ), roomMembershipDetails = { - Result.success( - RoomMembershipDetails( - currentUserMember = aRoomMember(userId = A_USER_ID, displayName = "Alice"), - senderMember = aRoomMember(userId = A_USER_ID_2, displayName = "Bob"), - ) - ) + Result.success(aRoomMembershipDetails()) } ) ) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -757,15 +811,15 @@ class JoinRoomPresenterTest { ), roomMembershipDetails = { Result.success( - RoomMembershipDetails( - currentUserMember = aRoomMember(userId = A_USER_ID, displayName = "Alice"), - senderMember = aRoomMember(userId = A_USER_ID_2, displayName = "Bob"), - ) + aRoomMembershipDetails(), ) } ) ) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -824,16 +878,14 @@ class JoinRoomPresenterTest { currentUserMembership = CurrentUserMembership.KNOCKED, ), roomMembershipDetails = { - Result.success( - RoomMembershipDetails( - currentUserMember = aRoomMember(userId = A_USER_ID, displayName = "Alice"), - senderMember = aRoomMember(userId = A_USER_ID_2, displayName = "Bob"), - ) - ) + Result.success(aRoomMembershipDetails()) } ) ) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -866,9 +918,17 @@ class JoinRoomPresenterTest { val client = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.success( - aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Private)) + aRoomPreview( + info = aRoomPreviewInfo(joinRule = JoinRule.Private), + roomMembershipDetails = { + Result.success(aRoomMembershipDetails()) + }, + ) ) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -886,9 +946,17 @@ class JoinRoomPresenterTest { val client = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.success( - aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Custom("custom"))) + aRoomPreview( + info = aRoomPreviewInfo(joinRule = JoinRule.Custom("custom")), + roomMembershipDetails = { + Result.success(aRoomMembershipDetails()) + }, + ) ) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -906,9 +974,17 @@ class JoinRoomPresenterTest { val client = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.success( - aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Invite)) + aRoomPreview( + info = aRoomPreviewInfo(joinRule = JoinRule.Invite), + roomMembershipDetails = { + Result.success(aRoomMembershipDetails()) + }, + ) ) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -926,9 +1002,19 @@ class JoinRoomPresenterTest { val client = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.success( - aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.KnockRestricted(persistentListOf()))) + aRoomPreview( + info = aRoomPreviewInfo( + joinRule = JoinRule.KnockRestricted(persistentListOf()) + ), + roomMembershipDetails = { + Result.success(aRoomMembershipDetails()) + } + ) ) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -946,9 +1032,17 @@ class JoinRoomPresenterTest { val client = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.success( - aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Restricted(persistentListOf()))) + aRoomPreview( + info = aRoomPreviewInfo(joinRule = JoinRule.Restricted(persistentListOf())), + roomMembershipDetails = { + Result.success(aRoomMembershipDetails()) + }, + ) ) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -966,7 +1060,10 @@ class JoinRoomPresenterTest { val client = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -996,7 +1093,10 @@ class JoinRoomPresenterTest { val client = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(AN_EXCEPTION) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -1021,7 +1121,10 @@ class JoinRoomPresenterTest { val client = FakeMatrixClient( getNotJoinedRoomResult = { _, _ -> Result.failure(ClientException.MatrixApi(ErrorKind.Forbidden, "403", "Forbidden", null)) - } + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), ) val presenter = createJoinRoomPresenter( matrixClient = client @@ -1060,7 +1163,11 @@ internal fun createJoinRoomPresenter( roomDescription: Optional = Optional.empty(), serverNames: List = emptyList(), trigger: JoinedRoom.Trigger = JoinedRoom.Trigger.Invite, - matrixClient: MatrixClient = FakeMatrixClient(), + matrixClient: MatrixClient = FakeMatrixClient( + spaceService = FakeSpaceService( + spaceRoomListResult = { FakeSpaceRoomList() }, + ), + ), joinRoomLambda: (RoomIdOrAlias, List, JoinedRoom.Trigger) -> Result = { _, _, _ -> Result.success(Unit) }, @@ -1087,3 +1194,8 @@ internal fun createJoinRoomPresenter( seenInvitesStore = seenInvitesStore, ) } + +private fun aRoomMembershipDetails() = RoomMembershipDetails( + currentUserMember = aRoomMember(userId = A_USER_ID, displayName = "Alice"), + senderMember = aRoomMember(userId = A_USER_ID_2, displayName = "Bob"), +) diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt index 0205c1cac0..f3487a43b6 100644 --- a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt @@ -14,7 +14,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.invite.api.InviteData import io.element.android.features.invite.test.anInviteData import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.matrix.api.room.RoomType import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.libraries.matrix.ui.model.toInviteSender @@ -218,21 +217,6 @@ class JoinRoomViewTest { eventsRecorder.assertSingle(JoinRoomEvents.RetryFetchingContent) } - @Test - fun `clicking on ok when a space is displayed invokes the expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) - ensureCalledOnce { - rule.setJoinRoomView( - aJoinRoomState( - contentState = aLoadedContentState(roomType = RoomType.Space), - eventSink = eventsRecorder, - ), - onBackClick = it - ) - rule.clickOn(CommonStrings.action_ok) - } - } - @Test fun `clicking on ok when user is unauthorized the expected callback`() { val eventsRecorder = EventsRecorder(expectEvents = false) From 67f9c24695f788ecc4f1ce9e539dcb899e4c9162 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Sep 2025 15:47:34 +0200 Subject: [PATCH 117/145] Localazy --- .../io/element/android/features/joinroom/impl/JoinRoomView.kt | 2 +- features/joinroom/impl/src/main/res/values/localazy.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 807d476a99..9430f15b30 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -442,7 +442,7 @@ private fun InvitedByView( horizontalAlignment = Alignment.CenterHorizontally ) { Text( - text = "Invited by", + text = stringResource(R.string.screen_join_room_invited_by), style = ElementTheme.typography.fontBodyMdRegular, color = ElementTheme.colors.textSecondary ) diff --git a/features/joinroom/impl/src/main/res/values/localazy.xml b/features/joinroom/impl/src/main/res/values/localazy.xml index f08807bd40..3d6a319aa6 100644 --- a/features/joinroom/impl/src/main/res/values/localazy.xml +++ b/features/joinroom/impl/src/main/res/values/localazy.xml @@ -15,6 +15,7 @@ "This room is either invite-only or there might be restrictions to access at space level." "Forget this room" "You need an invite in order to join this room" + "Invited by" "Join room" "You may need to be invited or be a member of a space in order to join." "Send request to join" From d8ccbcf0ededcbb512608f8a17487022bcb3ba1e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Sep 2025 16:26:33 +0200 Subject: [PATCH 118/145] Introduce LoadedDetails, different for Room and Space. --- .../joinroom/impl/JoinRoomPresenter.kt | 41 +++++++++++-------- .../features/joinroom/impl/JoinRoomState.kt | 20 ++++++--- .../joinroom/impl/JoinRoomStateProvider.kt | 32 ++++++++++----- .../features/joinroom/impl/JoinRoomView.kt | 4 +- .../joinroom/impl/JoinRoomPresenterTest.kt | 25 +++-------- .../impl/spaces/RustSpaceRoomListTest.kt | 5 ++- 6 files changed, 71 insertions(+), 56 deletions(-) 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 74ab8151c3..cb7ad57837 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 @@ -255,8 +255,6 @@ private fun RoomPreviewInfo.toContentState(membershipDetails: RoomMembershipDeta topic = topic, alias = canonicalAlias, numberOfMembers = numberOfJoinedMembers, - isDm = false, - roomType = roomType, roomAvatarUrl = avatarUrl, joinAuthorisationStatus = computeJoinAuthorisationStatus( membership, @@ -265,8 +263,16 @@ private fun RoomPreviewInfo.toContentState(membershipDetails: RoomMembershipDeta { toInviteData() } ), joinRule = joinRule, - childrenCount = null, - heroes = persistentListOf(), + details = when (roomType) { + is RoomType.Other, + RoomType.Room -> LoadedDetails.Room( + isDm = false, + ) + RoomType.Space -> LoadedDetails.Space( + childrenCount = 0, + heroes = persistentListOf(), + ) + } ) } @@ -277,8 +283,6 @@ private fun SpaceRoom.toContentState(): ContentState { topic = topic, alias = canonicalAlias, numberOfMembers = numJoinedMembers.toLong(), - isDm = false, - roomType = roomType, roomAvatarUrl = avatarUrl, joinAuthorisationStatus = computeJoinAuthorisationStatus( membership = state, @@ -286,9 +290,11 @@ private fun SpaceRoom.toContentState(): ContentState { joinRule = joinRule, inviteData = { toInviteData() } ), - childrenCount = childrenCount, joinRule = joinRule, - heroes = heroes.toPersistentList(), + details = LoadedDetails.Space( + childrenCount = childrenCount, + heroes = heroes.toPersistentList(), + ) ) } @@ -300,15 +306,12 @@ internal fun RoomDescription.toContentState(): ContentState { topic = topic, alias = alias, numberOfMembers = numberOfMembers, - isDm = false, - roomType = RoomType.Room, roomAvatarUrl = avatarUrl, joinAuthorisationStatus = when (joinRule) { RoomDescription.JoinRule.KNOCK -> JoinAuthorisationStatus.CanKnock RoomDescription.JoinRule.PUBLIC -> JoinAuthorisationStatus.CanJoin else -> JoinAuthorisationStatus.Unknown }, - childrenCount = null, joinRule = when (joinRule) { RoomDescription.JoinRule.KNOCK -> JoinRule.Knock RoomDescription.JoinRule.PUBLIC -> JoinRule.Public @@ -317,7 +320,7 @@ internal fun RoomDescription.toContentState(): ContentState { RoomDescription.JoinRule.INVITE -> JoinRule.Invite RoomDescription.JoinRule.UNKNOWN -> null }, - heroes = persistentListOf() + details = LoadedDetails.Room(isDm = false) ) } @@ -333,8 +336,6 @@ internal fun RoomInfo.toContentState( topic = topic, alias = canonicalAlias, numberOfMembers = joinedMembersCountOverride ?: joinedMembersCount, - isDm = isDm, - roomType = if (isSpace) RoomType.Space else RoomType.Room, roomAvatarUrl = avatarUrl, joinAuthorisationStatus = computeJoinAuthorisationStatus( membership = currentUserMembership, @@ -343,8 +344,16 @@ internal fun RoomInfo.toContentState( inviteData = { toInviteData() } ), joinRule = joinRule, - childrenCount = childrenCount, - heroes = heroes + details = if (isSpace) { + LoadedDetails.Space( + childrenCount = childrenCount ?: 0, + heroes = heroes, + ) + } else { + LoadedDetails.Room( + isDm = isDm, + ) + }, ) } 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 6ecdcf4ba2..f27a290f5d 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 @@ -16,7 +16,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize 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.room.RoomType import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.user.MatrixUser @@ -77,16 +76,13 @@ sealed interface ContentState { val topic: String?, val alias: RoomAlias?, val numberOfMembers: Long?, - val isDm: Boolean, - val roomType: RoomType, val roomAvatarUrl: String?, val joinAuthorisationStatus: JoinAuthorisationStatus, val joinRule: JoinRule?, - val childrenCount: Int?, - val heroes: ImmutableList, + val details: LoadedDetails, ) : ContentState { val showMemberCount = numberOfMembers != null - val isSpace = roomType is RoomType.Space + val isSpace = details is LoadedDetails.Space fun avatarData(size: AvatarSize): AvatarData { return AvatarData( @@ -99,6 +95,18 @@ sealed interface ContentState { } } +@Immutable +sealed interface LoadedDetails { + data class Room( + val isDm: Boolean, + ) : LoadedDetails + + data class Space( + val childrenCount: Int, + val heroes: ImmutableList, + ) : LoadedDetails +} + sealed interface JoinAuthorisationStatus { data object None : JoinAuthorisationStatus data class IsInvited(val inviteData: InviteData, val inviteSender: InviteSender?) : JoinAuthorisationStatus diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 404b219dc9..8eeecab83c 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -20,7 +20,6 @@ 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.exception.ClientException -import io.element.android.libraries.matrix.api.room.RoomType import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.user.MatrixUser @@ -80,14 +79,17 @@ open class JoinRoomStateProvider : PreviewParameterProvider { name = "A space", alias = null, topic = "This is the topic of a space", - roomType = RoomType.Space, - childrenCount = 42, + details = aLoadedDetailsSpace( + childrenCount = 42, + ), ) ), aJoinRoomState( contentState = aLoadedContentState( name = "A DM", - isDm = true, + details = aLoadedDetailsRoom( + isDm = true, + ), ) ), aJoinRoomState( @@ -160,25 +162,33 @@ fun aLoadedContentState( alias: RoomAlias? = RoomAlias("#exa:matrix.org"), topic: String? = "Element X is a secure, private and decentralized messenger.", numberOfMembers: Long? = null, - isDm: Boolean = false, - roomType: RoomType = RoomType.Room, roomAvatarUrl: String? = null, joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown, - childrenCount: Int? = null, joinRule: JoinRule? = null, - heroes: List = emptyList() + details: LoadedDetails = aLoadedDetailsRoom(isDm = false), ) = ContentState.Loaded( roomId = roomId, name = name, alias = alias, topic = topic, numberOfMembers = numberOfMembers, - isDm = isDm, - roomType = roomType, roomAvatarUrl = roomAvatarUrl, joinAuthorisationStatus = joinAuthorisationStatus, - childrenCount = childrenCount, joinRule = joinRule, + details = details, +) + +fun aLoadedDetailsRoom( + isDm: Boolean = false, +) = LoadedDetails.Room( + isDm = isDm +) + +fun aLoadedDetailsSpace( + childrenCount: Int = 0, + heroes: List = emptyList(), +) = LoadedDetails.Space( + childrenCount = childrenCount, heroes = heroes.toPersistentList() ) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 9430f15b30..6da7aadfe7 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -566,10 +566,10 @@ private fun DefaultLoadedContent( }, subtitle = { when { - contentState.isSpace -> { + contentState.details is LoadedDetails.Space -> { SpaceInfoRow( joinRule = contentState.joinRule ?: JoinRule.Public, - numberOfRooms = contentState.childrenCount ?: 0, + numberOfRooms = contentState.details.childrenCount, ) } contentState.alias != null -> { 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 ee4b2625fd..9d4b16c1f3 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 @@ -33,7 +33,6 @@ import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.matrix.api.exception.ErrorKind import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomMembershipDetails -import io.element.android.libraries.matrix.api.room.RoomType import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.test.AN_EXCEPTION @@ -111,7 +110,7 @@ class JoinRoomPresenterTest { assertThat(contentState.topic).isEqualTo(roomInfo.topic) assertThat(contentState.alias).isEqualTo(roomInfo.canonicalAlias) assertThat(contentState.numberOfMembers).isEqualTo(roomInfo.joinedMembersCount) - assertThat(contentState.isDm).isEqualTo(roomInfo.isDirect) + assertThat(contentState.details).isEqualTo(aLoadedDetailsRoom(isDm = roomInfo.isDirect)) assertThat(contentState.roomAvatarUrl).isEqualTo(roomInfo.avatarUrl) } } @@ -464,7 +463,7 @@ class JoinRoomPresenterTest { assertThat(contentState.topic).isEqualTo(roomDescription.topic) assertThat(contentState.alias).isEqualTo(roomDescription.alias) assertThat(contentState.numberOfMembers).isEqualTo(roomDescription.numberOfMembers) - assertThat(contentState.isDm).isFalse() + assertThat(contentState.details).isEqualTo(aLoadedDetailsRoom(isDm = false)) assertThat(contentState.roomAvatarUrl).isEqualTo(roomDescription.avatarUrl) } } @@ -708,13 +707,10 @@ class JoinRoomPresenterTest { topic = "Room topic", alias = RoomAlias("#alias:matrix.org"), numberOfMembers = 2, - isDm = false, - roomType = RoomType.Room, roomAvatarUrl = "avatarUrl", joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin, joinRule = JoinRule.Public, - childrenCount = null, - heroes = persistentListOf() + details = aLoadedDetailsRoom(isDm = false), ) ) } @@ -762,8 +758,6 @@ class JoinRoomPresenterTest { topic = "Room topic", alias = RoomAlias("#alias:matrix.org"), numberOfMembers = 2, - isDm = false, - roomType = RoomType.Room, roomAvatarUrl = "avatarUrl", joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited( inviteData = InviteData( @@ -783,8 +777,7 @@ class JoinRoomPresenterTest { ), ), joinRule = JoinRule.Public, - childrenCount = null, - heroes = persistentListOf() + details = aLoadedDetailsRoom(isDm = false), ) ) } @@ -834,8 +827,6 @@ class JoinRoomPresenterTest { topic = "Room topic", alias = RoomAlias("#alias:matrix.org"), numberOfMembers = 2, - isDm = false, - roomType = RoomType.Room, roomAvatarUrl = "avatarUrl", joinAuthorisationStatus = JoinAuthorisationStatus.IsBanned( banSender = InviteSender( @@ -851,8 +842,7 @@ class JoinRoomPresenterTest { reason = null, ), joinRule = JoinRule.Public, - childrenCount = null, - heroes = persistentListOf() + details = aLoadedDetailsRoom(isDm = false), ) ) } @@ -900,13 +890,10 @@ class JoinRoomPresenterTest { topic = "Room topic", alias = RoomAlias("#alias:matrix.org"), numberOfMembers = 2, - isDm = false, - roomType = RoomType.Room, roomAvatarUrl = "avatarUrl", joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked, joinRule = JoinRule.Public, - childrenCount = null, - heroes = persistentListOf() + details = aLoadedDetailsRoom(isDm = false), ) ) } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt index 6ef3259657..3d4cb98abc 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt @@ -26,6 +26,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Test import org.matrix.rustcomponents.sdk.SpaceListUpdate import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState +import kotlin.jvm.optionals.getOrNull import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList class RustSpaceRoomListTest { @@ -93,10 +94,10 @@ class RustSpaceRoomListTest { spaceRoomCache = spaceRoomCache, ) sut.currentSpaceFlow().test { - assertThat(awaitItem()).isNull() + assertThat(awaitItem().getOrNull()).isNull() val spaceRoom = aSpaceRoom(roomId = A_ROOM_ID) spaceRoomCache.update(listOf(spaceRoom)) - assertThat(awaitItem()).isEqualTo(spaceRoom) + assertThat(awaitItem().getOrNull()).isEqualTo(spaceRoom) } } From 18224894bd62e5468a9fa4db0f278d85f663c709 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 22 Sep 2025 16:28:46 +0200 Subject: [PATCH 119/145] fix (timeline) : forward pagination regression --- .../android/libraries/matrix/impl/timeline/RustTimeline.kt | 3 +-- .../timeline/postprocessor/LoadingIndicatorsPostProcessor.kt | 3 +-- .../postprocessor/LoadingIndicatorsPostProcessorTest.kt | 4 ---- 3 files changed, 2 insertions(+), 8 deletions(-) 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 b4888dafe0..4c52e78205 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 @@ -123,7 +123,7 @@ class RustTimeline( ) override val forwardPaginationStatus = MutableStateFlow( - Timeline.PaginationStatus(isPaginating = false, hasMoreToLoad = mode !is Timeline.Mode.FocusedOnEvent) + Timeline.PaginationStatus(isPaginating = false, hasMoreToLoad = mode is Timeline.Mode.FocusedOnEvent) ) init { @@ -221,7 +221,6 @@ class RustTimeline( items = items, hasMoreToLoadBackward = backwardPaginationStatus.hasMoreToLoad, hasMoreToLoadForward = forwardPaginationStatus.hasMoreToLoad, - timelineMode = mode, ) } .let { items -> diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt index 22b70b1d35..6d42af54b5 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt @@ -18,9 +18,8 @@ class LoadingIndicatorsPostProcessor(private val systemClock: SystemClock) { items: List, hasMoreToLoadBackward: Boolean, hasMoreToLoadForward: Boolean, - timelineMode: Timeline.Mode, ): List { - val shouldAddForwardLoadingIndicator = timelineMode is Timeline.Mode.Live && hasMoreToLoadForward && items.isNotEmpty() + val shouldAddForwardLoadingIndicator = hasMoreToLoadForward && items.isNotEmpty() val currentTimestamp = systemClock.epochMillis() return buildList { if (hasMoreToLoadBackward) { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt index c92fb9776b..881d718392 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt @@ -24,7 +24,6 @@ class LoadingIndicatorsPostProcessorTest { items = listOf(messageEvent, messageEvent2), hasMoreToLoadBackward = true, hasMoreToLoadForward = false, - timelineMode = Timeline.Mode.Live, ) assertThat(result).containsExactly( MatrixTimelineItem.Virtual( @@ -47,7 +46,6 @@ class LoadingIndicatorsPostProcessorTest { items = listOf(messageEvent, messageEvent2), hasMoreToLoadBackward = false, hasMoreToLoadForward = true, - timelineMode = Timeline.Mode.Live, ) assertThat(result).containsExactly( messageEvent, @@ -70,7 +68,6 @@ class LoadingIndicatorsPostProcessorTest { items = listOf(messageEvent, messageEvent2), hasMoreToLoadBackward = true, hasMoreToLoadForward = true, - timelineMode = Timeline.Mode.Live, ) assertThat(result).containsExactly( MatrixTimelineItem.Virtual( @@ -100,7 +97,6 @@ class LoadingIndicatorsPostProcessorTest { items = listOf(), hasMoreToLoadBackward = true, hasMoreToLoadForward = true, - timelineMode = Timeline.Mode.Live, ) assertThat(result).containsExactly( MatrixTimelineItem.Virtual( From e8ddee760cac4c0a76f6aa2fea52ab3f78f716fa Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 22 Sep 2025 14:42:36 +0000 Subject: [PATCH 120/145] Update screenshots --- .../features.home.impl.spaces_HomeSpacesView_Day_0_en.png | 4 ++-- .../features.home.impl.spaces_HomeSpacesView_Day_1_en.png | 4 ++-- .../features.home.impl.spaces_HomeSpacesView_Night_0_en.png | 4 ++-- .../features.home.impl.spaces_HomeSpacesView_Night_1_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_0_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_10_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_11_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_12_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_13_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_14_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_15_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_16_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_1_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_2_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_3_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_4_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_5_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_6_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_7_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_8_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Day_9_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_0_en.png | 4 ++-- .../features.joinroom.impl_JoinRoomView_Night_10_en.png | 4 ++-- .../features.joinroom.impl_JoinRoomView_Night_11_en.png | 4 ++-- .../features.joinroom.impl_JoinRoomView_Night_12_en.png | 4 ++-- .../features.joinroom.impl_JoinRoomView_Night_13_en.png | 4 ++-- .../features.joinroom.impl_JoinRoomView_Night_14_en.png | 4 ++-- .../features.joinroom.impl_JoinRoomView_Night_15_en.png | 4 ++-- .../features.joinroom.impl_JoinRoomView_Night_16_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_1_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_2_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_3_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_4_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_5_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_6_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_7_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_8_en.png | 4 ++-- .../images/features.joinroom.impl_JoinRoomView_Night_9_en.png | 4 ++-- ....roomaliasresolver.impl_RoomAliasResolverView_Day_0_en.png | 4 ++-- ....roomaliasresolver.impl_RoomAliasResolverView_Day_1_en.png | 4 ++-- ....roomaliasresolver.impl_RoomAliasResolverView_Day_2_en.png | 4 ++-- ...oomaliasresolver.impl_RoomAliasResolverView_Night_0_en.png | 4 ++-- ...oomaliasresolver.impl_RoomAliasResolverView_Night_1_en.png | 4 ++-- ...oomaliasresolver.impl_RoomAliasResolverView_Night_2_en.png | 4 ++-- .../images/features.space.impl_SpaceView_Day_0_en.png | 4 ++-- .../images/features.space.impl_SpaceView_Day_1_en.png | 4 ++-- .../images/features.space.impl_SpaceView_Day_2_en.png | 4 ++-- .../images/features.space.impl_SpaceView_Day_3_en.png | 4 ++-- .../images/features.space.impl_SpaceView_Night_0_en.png | 4 ++-- .../images/features.space.impl_SpaceView_Night_1_en.png | 4 ++-- .../images/features.space.impl_SpaceView_Night_2_en.png | 4 ++-- .../images/features.space.impl_SpaceView_Night_3_en.png | 4 ++-- ...s.designsystem.components.avatar_Avatar_Avatars_102_en.png | 4 ++-- ...s.designsystem.components.avatar_Avatar_Avatars_103_en.png | 4 ++-- ...s.designsystem.components.avatar_Avatar_Avatars_104_en.png | 4 ++-- ...s.designsystem.components.avatar_Avatar_Avatars_105_en.png | 3 +++ ...s.designsystem.components.avatar_Avatar_Avatars_106_en.png | 3 +++ ...s.designsystem.components.avatar_Avatar_Avatars_107_en.png | 3 +++ ...s.designsystem.components.avatar_Avatar_Avatars_108_en.png | 3 +++ ...s.designsystem.components.avatar_Avatar_Avatars_109_en.png | 3 +++ ...s.designsystem.components.avatar_Avatar_Avatars_110_en.png | 3 +++ ...ies.designsystem.components.avatar_Avatar_Avatars_6_en.png | 4 ++-- ...ies.designsystem.components.avatar_Avatar_Avatars_7_en.png | 4 ++-- ...ies.designsystem.components.avatar_Avatar_Avatars_8_en.png | 4 ++-- ...ibraries.matrix.ui.components_SpaceHeaderView_Day_0_en.png | 4 ++-- ...raries.matrix.ui.components_SpaceHeaderView_Night_0_en.png | 4 ++-- 66 files changed, 138 insertions(+), 120 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_108_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_109_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_110_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_0_en.png index f36c5aa998..df4bd9bbc2 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4053802814238aa74a5c606a4b37e0afcb923282c3e7cece737b0ec4f6828351 -size 106332 +oid sha256:fbdebc1c9361339dd0db1051e59162ed62fa2787c46457848da5ee6a30474588 +size 106570 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_1_en.png index a715ddb59f..60ab311cdc 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04ec1bd0bd667d5319843f480f2b7ca4b1b4364db4fbe22d85c10d291891642a -size 42696 +oid sha256:7a6d3be47ab7d9234657d4d088389c8aadb4d9e073d8c91f4f81dded1b6662a6 +size 42160 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_0_en.png index b77735afed..66babf5423 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d02259f3163c49b5c39d38d7a84af50583f6a0ce2a66e8ad013ac18278de65c0 -size 103621 +oid sha256:7bb7d1c08f5b2551117aa1aff8a3afbabd0f4100e0fae11cf415bd8e851c0307 +size 103835 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_1_en.png index b814fce01e..2b50f7350b 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d00883e68471491d8edf06eee394e4310707dbd03782f57bb7f783822790b61 -size 41372 +oid sha256:b3f70a15def31e67e84afe7f9545d280bdbca01c6dd63864662f19976df3bf33 +size 40960 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_0_en.png index 41c9460979..fc843bc4f5 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7423c3f11ec8661d7fb3f57d7d78459e784221644229515080e0b0dc6ce59b6e -size 10129 +oid sha256:8c88f9a3ecbcf7db13846a6074c75fca2ce6bdbe0edd850bfc139e01a4fdc0c8 +size 9956 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_10_en.png index bb3bc2a09c..4f172d6a06 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08ed98b594a6730d52ab344aff6bea8a38216a609549be267f9046dd69858903 -size 38478 +oid sha256:7fdd74d6df903a0cedfbfc2f30430b5802e4f0bc7b2711e20ae47d297066b056 +size 40297 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_11_en.png index 97af44e438..ce1e584d59 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf0a1c9fea2a067d6156985cce2fd2a2551f6111e7739206f7bd70a563a97fcf -size 45333 +oid sha256:ed26457abf2a6d89d61e911944b4e9f62de248c1939f997d0f8764e4c1ae08e9 +size 43088 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_12_en.png index 4176533a78..ad220df759 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24d9f9b2a63773f5bc49b7f8f8b85d1dd13e8e62175b61bca534b04626d19b0f -size 46336 +oid sha256:46b410cba77b24d8657031f5fde29d4f25a639300862641ce0f8ad0de8ff99cb +size 44076 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_13_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_13_en.png index c737e362de..af3739d987 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca5217bba4fe65af4ac2a0aaaefa941a5a5ed0735dbd9bd69a648a157ca0c51b -size 29343 +oid sha256:950e90b7c2c67fc95c9d6698dc7436885ee80dcf9da7d8467b0027c04c03c8f5 +size 29243 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_14_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_14_en.png index f3ad94a6a5..0834071308 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:41a3c9cbec371b6aacabcb954315a65939b579c5963db63fc11789326ad2fc1b -size 29068 +oid sha256:37ac3a032e758c4abf9ac8a87e887c7e015f2d35160d59a7e263963300bd0941 +size 31558 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_15_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_15_en.png index 70d7d9d00e..330bd7edc7 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0249fb4df9e88abaa28cc3a10e2cadc23b3b84581d74893d525076683f0a5588 -size 36386 +oid sha256:44b9c4608696c6a690e7f00f661b3cb55d03826b11569b6e8ce0a48f9754dd39 +size 38547 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_16_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_16_en.png index 52411087a2..e9ce885cd8 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1c6c00bca10e0bf725ab5debe3cd9dbb14be89f29872ca70df8f3886d1cec19 -size 40928 +oid sha256:f92065e3de67f39ce27ae3e321f59fa2d18b5927752dc760450ec275935b1959 +size 43405 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 66639e1bc2..c127d5b02f 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:96ecb81ebfc7545eca7931538a443b7190b7903d8ebf5bf70bb95eb3b42e6a38 -size 30092 +oid sha256:919101bfd215af97a098bdfae4980445bd1d0560f96fe9ce13a870e2d8817fff +size 34247 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_2_en.png index b28d9d527d..a902aef055 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:09e79f148754898125af4972bbfecfb1e3fc8f2de918ba9dd12d9766ef09e4f1 -size 31417 +oid sha256:2f9707b754041c871c408e12613faa186fa4f4f760ca793caf20c62bae07246b +size 32021 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_3_en.png index 461aaa3497..16ac399dbf 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c87682ca77c0ee163e437dae9f177e52937c6099e1d3583f2138735fd5ecc8f -size 26669 +oid sha256:5ad9105ca2659f51b16b41f9317812590f38adb8431a64a139bb47f54fdf9eff +size 29754 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_4_en.png index 488b2ef5d5..78b8500823 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8319fdce8ae47fd6dc7aea8f6c98e9e4de7322f0b9adc4262695ff3990a63052 -size 39520 +oid sha256:04180611d2a959d07bbbd051c4386f6428d841c5ea74e197a80149370db76e04 +size 41830 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png index 5a80c8299e..644110ef6d 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ae6db46d01c157fcb8bb436b43e38da13723c498a222e68f792ac170ea2e2ac -size 27841 +oid sha256:7c4a828b9aa4e4963e3cb39e6f65f82ff5e595fdccb4dc5b48db532eeac1fb00 +size 31388 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_6_en.png index ce70cfc15f..c7d05de034 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:484657673c4ae676b330320ba213485a16c6f31ea025b16b4f2c3a53053eaf7a -size 29860 +oid sha256:bdc24799de625f9826fcf87a624e76b530e7f0e44c294d49f842ed2de7a9c085 +size 32981 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_7_en.png index 1484121044..3d78e94953 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a239f4f8003693097fee6e9dddc31ed1ce7a53f7c2b9dab9db55059ca51df64f -size 37645 +oid sha256:247a1cec9f0729ef1b23dc5ad730521bb7bfc117b4e9cc901ec922ee946f942e +size 39401 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png index abf5b32866..c6f8b658a3 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e10c07c74c54920daac28945f2fcafb8956edcd6df5aaac1d7dc757bd119ee3d -size 26750 +oid sha256:bcc00accf1fa84c48831378faa27558d5ba24961dd3ba0c5f0587329cdbaa9bf +size 29110 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_9_en.png index 74638ec5ac..cc08744b50 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:657dfa3cd260803b3386ae6c3d44f6cc4277c2ef2572680145c419dfd9690e7a -size 33276 +oid sha256:da07e3041ec5814feb0d14e8478d0c817d1496155db2daa612048b94530df20b +size 38200 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_0_en.png index 37396ce4d7..636b7ba0e6 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58776319728d3367a347d62cf120803582b05c564f9cd76b2c8f406e70673821 -size 9949 +oid sha256:c91724171606aa0c36987908af0abce5c05b3311469a08e532532307d1224c60 +size 9842 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_10_en.png index 7d9743ada7..edc2a732b6 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ae699d09bc1287d12d9974a6801f6b1648f0d6bd63eb9ac10302be37cae5383 -size 38181 +oid sha256:f5a6da57cc5659ba3f3705cba41fd23c7628ba2477fcfc427b8e26bde37ed812 +size 39960 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_11_en.png index 6cdda44336..5f8961f485 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:511985d79fe13467eec62772dbe6cc69dec1f1c9f9a3e66428fe9b22ce279d1f -size 44937 +oid sha256:5b9cf46f0039e0f91e8372cd5f9a15b7b54b75c80e0a38f9ebc2548315d57c9f +size 42657 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_12_en.png index a1fd91d0a7..c25392b215 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a084ed7657a2f263283a477e700df9fb6219e8268380f764c2e5e4055465044d -size 45898 +oid sha256:5a4f65342c0e84179aceadc5d75fc763ed45c23f4db44bc16441c50990b193ed +size 43582 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_13_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_13_en.png index f2c3b773b4..9c134bf310 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:51680be3eede0c4a53683b298415a07f3e9ea688ac39fe29373e1e80b0f4540b -size 28778 +oid sha256:e2ef8069be91c6e20263da790c0b8b777515f46bdc4769532b321ae86c9152b8 +size 28701 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_14_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_14_en.png index 485ba35c62..867ef2ea72 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7172438656b08d5c244fc570fd25dc074562b7599f15eda8241ddb7c9b275fcd -size 28765 +oid sha256:5f47c18fda5c4839e1098955f57c4a3e5b9856203c6a84c31903aa5e0b2da46b +size 30971 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_15_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_15_en.png index 4ab802917f..40257d2267 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9aaf1721d3b8c3a000402eb605b7ba742560fae7297514a15f74fd97c2f838a1 -size 35406 +oid sha256:112286f6a18865db2333a68cb804e930eb873bb04596bada2f825e2223b4f537 +size 37362 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_16_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_16_en.png index 40682697ef..abc81a0d58 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7b113b174727ce08ed2b23f320d49b556e869249302c0b84c1b5916ae8864ac -size 40563 +oid sha256:ff86f906357d0bf611bfc9cd235e66e0247dd7bb66903cb0e5730224d5dc897c +size 43008 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 251f240e62..b480466344 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:444f717f986b154297294df6ba731befc3e2049f89a3294e26fd6d90f0831996 -size 29353 +oid sha256:cc849f3158de5cd3cdc64a57e613f3b3a5cd70794e7984d7cfa1f8f425184592 +size 33440 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_2_en.png index 2126595abd..9869f158e6 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9bd6d13f3c4f7a715e9e8698db252bc33823fe180e6d279eabcc9de618dcaee -size 31182 +oid sha256:ed211c9bc258185de6ea4cc414fd214f256ad1649c26a8a28f25fd1b29c34783 +size 31630 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_3_en.png index be61677a61..42619d6321 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:acdd2cd73f2a37190bbbeb829af68a28dae8d73f5462396db4c6238ee8319351 -size 26733 +oid sha256:6a88ffdfd4259a2e85b3a8375591eab3b0f12e927eb83f9c6820995acf44d79e +size 29607 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_4_en.png index c484f2aeff..1b95755ca6 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:731f81d6ca0d4677dc56b58316c7396a7ad1ee08c785aecbb9eea4a0dea6b77a -size 38428 +oid sha256:7fbe20a3d4e0c3706ce81c1f52c65ff4f749b0afd6bdd3efb4100ee1019afc51 +size 40580 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png index 05ee8fba6c..0211928122 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d3a672f30777ff5b487bca938e612de8e34de94dc5ac189659ced73ed49bffa -size 26309 +oid sha256:cff1f0a8a34cfd4eb55487540a02c70e629d7f6123355c95380498817053eb78 +size 29575 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_6_en.png index 76d730668b..f599f084b6 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e0d60be4104d5f124e49e8a7434204bd0593b46fca838e787aefa40769ac1778 -size 29202 +oid sha256:71e56b906decbea31fcf5581dc92dcbb6be79f6a6962595786e9533cc62254ad +size 32045 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_7_en.png index 799003fe8e..4f8d2856a4 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7129f65572d7b4f6b302fa803f878b269f2ee7b11a684c3e1ec051f9192fc8fa -size 36927 +oid sha256:18e36242d664e1f2179bb3aef3f77a5bbbf5cd44aece2d2c9a3d7d70d2356b92 +size 38769 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png index 436ec07c51..b595df5d84 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83b636552b1a28db8bb81e870486acd861ee131f51f8a8980fb3f1471e55ba3f -size 24709 +oid sha256:37270eed539ed52a113375dbfa516f443838530ef7995bb6372764afbc25e75d +size 26787 diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_9_en.png index 5098ca7b17..8af0e7e350 100644 --- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c862dd75be71248752d53cc605860c55fe4eecce75eba545ab4471a13585296 -size 32951 +oid sha256:0b73e8a2429db6324f471908f46ccd2f6723d59caf4acc738c07d6e402a19285 +size 37752 diff --git a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en.png index 8cb0a46709..31eb958563 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b0c1728d598c5bf307a2b9a193c2746831c83de892fc53ccb7da1bb183b8297 -size 8475 +oid sha256:6d4663e9c2c439b05d6d1abe7ae7098539f5263461e9051b0b97305a31b5aa33 +size 8395 diff --git a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en.png index abf5b32866..947b0607e5 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e10c07c74c54920daac28945f2fcafb8956edcd6df5aaac1d7dc757bd119ee3d -size 26750 +oid sha256:5365eb3dd7e10fde8591e6d5ee6dfadef88a9fa25339309ce08445f89af88789 +size 29187 diff --git a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en.png index 282404ccf8..6faf40fe01 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78826ac37783b67bab2ef7c93a5ad1fcc1fd167926ed3e6d8c92eb826c8b603f -size 23462 +oid sha256:5c66ca10f770fa2f29716f7c737be0acef03e364e9a27a85b81e4ef63e768b6f +size 24012 diff --git a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en.png index 0c7e27a22d..26a56fec35 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3f39d62131784e82104ee0033e4da9e2de45eacc1527b878fdaa9dd64d45aa2 -size 8324 +oid sha256:c5b7cb8b7ef8b58a5fa77b7c1c6a911798940337ea9646383ee0cb082dc68f7e +size 8263 diff --git a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en.png index 436ec07c51..a6bed8f351 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83b636552b1a28db8bb81e870486acd861ee131f51f8a8980fb3f1471e55ba3f -size 24709 +oid sha256:c02fa02a7f5787d375ffa6e9bb69cde0b23ca87512ee8120d318becd6de13bef +size 26763 diff --git a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en.png index 2751f65665..a0b5cf90f0 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7114651af7b2d0ae7caf7df0bb81bb117fc829bd9795a57e173729673c23d231 -size 21082 +oid sha256:5852e500de1f27083f033726a89d2dda594497d2af7fbe843091cdbd06ddd975 +size 21628 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_0_en.png index 59cd1f1de1..47fc782a13 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e69f830b7f15de531fc46efc02964fb641a4e3754b5108fb8020e97bbfb4b56 -size 15698 +oid sha256:4c53e7edfe8b9ea00bb97f9ab6e8289081b5c36aad54a58d4f535fc533338797 +size 15733 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png index 393434d50b..a9623bcde8 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5fba00f44ab63c07978ec0143f2f1fefc8fd1d78aed22a367e831c105b806c7 -size 17306 +oid sha256:18bacb2019ed743c8cf023239b18cb438656eb523e6d0a54f692fe9d5d637270 +size 17322 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_2_en.png index 2fa59b0ada..80a6ed2561 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c7b387db1b0637745dfc93559b9afa3c637e5a492bf19f6f1d0dbe802ed73bb -size 47156 +oid sha256:9d784e5d4d4af937a33825f7098d0849fa044d96e4cf21c7244f51432d3f32c7 +size 46725 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_3_en.png index 8cb2f6776c..1c0ff9913e 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9892ec0c06bfa6e0b3a95fd35efa97e44f2e1f6264a324d6fdd994847f1830d1 -size 45897 +oid sha256:1a1c851207069720dd83cf32da6da80d25a4a4c40cba9884548f9dea09ca6654 +size 45383 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_0_en.png index a2c2d2043d..1de4e50542 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91ad7e392e21afe93606956e8e7eab7f0b075574e782ff15e873a71fc3ab16ab -size 15637 +oid sha256:ea671a40116dfe7a0e4ac97b58cbbc48b3f70fe08b5613c4b21ec13bc6850c3f +size 15589 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png index 67cdaf4a39..0cbaf3c23f 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d50be9f20ed0e75e337d790edb329996abf9e626591882088817301338fadb6 -size 17213 +oid sha256:9baf49cdfea6895362b19b780b4877e31b006304b1a92e47d47f941efbb773f4 +size 17165 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_2_en.png index 6e55a5816e..bd899f7f08 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d76f7b10d8c88f39ab36581be35dd2a5ca5e7c3a92c69b96d4f3ec87f2e93468 -size 46564 +oid sha256:ae27a6a05d85587b066203ec8828db0ec1cec2171e1f3a63c6b0c26e0b71555e +size 46151 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_3_en.png index 298a35ce39..b3c914f630 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:057ceb522ff354d0d7e8b73d59eb53c559f9c22a2727d24744dc6a34b9daaa55 -size 45034 +oid sha256:067d6b499ce3ec737792a773c2959aea44829cb27a8fecbe1925ec884bc7f53f +size 44650 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png index 7946dc4e91..7f55d277d5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce1aba18ea8a6b45d9c40de9af961952e261c7c6200ab13cdfa67906d995208b -size 14888 +oid sha256:8da97746633081690a09a79e3f9974257bbe0f292ad5b8ee2eed454c1273c01e +size 19747 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png index 0b12b366b9..91a2bc23da 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a4d295ae71ba2709845312b84983b79348069ded46b30091b9fa769a587cbb7 -size 14337 +oid sha256:1aaa84f80b3691ed83308966e53deb8dbc97c7943d2f68a8036a6ead603ea627 +size 18270 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png index 556cb141b0..a2cd42670a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da8f54591a52475c6f47fa083a1bb397e1164dd3e735562388fde4ff45644150 -size 16275 +oid sha256:ddaae721cac21a188dc3862e3e14e80eeb13c92826bccfb8364ecbd72948d9bd +size 23653 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png new file mode 100644 index 0000000000..885a613f50 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:207d569640554b3b11cadb03a231ae0dfd85a3c470695cc8428cb2e295d98776 +size 18858 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png new file mode 100644 index 0000000000..4279c36d24 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:68ae347075a6bef936e9c905a12b6b561a01737ab886436d73f4987783a1b45f +size 17541 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png new file mode 100644 index 0000000000..1ff47d58e0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8caa1fbeb5250684363a21549cdcfff60489059c9d1f0ca115503e63675b3511 +size 22394 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_108_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_108_en.png new file mode 100644 index 0000000000..7946dc4e91 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_108_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce1aba18ea8a6b45d9c40de9af961952e261c7c6200ab13cdfa67906d995208b +size 14888 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_109_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_109_en.png new file mode 100644 index 0000000000..0b12b366b9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_109_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a4d295ae71ba2709845312b84983b79348069ded46b30091b9fa769a587cbb7 +size 14337 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_110_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_110_en.png new file mode 100644 index 0000000000..556cb141b0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_110_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da8f54591a52475c6f47fa083a1bb397e1164dd3e735562388fde4ff45644150 +size 16275 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_6_en.png index 0622e6c69b..1bf67b7c98 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f52fa29e031ab362baed77ac18228960d67eb5d6bdf909b6c1fb3777f5eacc5 -size 19629 +oid sha256:8cb143e42d0bc07652d74c74ba641a5332ee9bebb071fa5efba59ecacad04be5 +size 21857 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_7_en.png index dccb49ff50..3db35531c4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b6a0bdd2239b473f541e95588f2531a2761d0d9872cda61cdd87e2e195b14cf -size 17425 +oid sha256:5eecc64fbbf67e53578ba6c974905c16d000a5dc8b2e0fa99c41e46dea36424b +size 19651 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_8_en.png index d1b6ea7f02..3f0469f5cc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3898d22d9de94323eb04d5385af9a1084434c521f8b51f5af74ef1159dd2d1cc -size 25138 +oid sha256:c425ffed237de0e71451baf51f674051c3ab6481ecceeff15c7f2f73193fd3ab +size 26866 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceHeaderView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceHeaderView_Day_0_en.png index 785ed41190..7a7bf57ab7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceHeaderView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceHeaderView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebb657ce2227ccefcf9055c8c90342d6581ac0d916cd9f7e6a4990fa2bdc4177 -size 61352 +oid sha256:21acaf9ea606378f5f1e83795e41bec9edc2da05143efba04b70f67cce2c80b0 +size 61626 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceHeaderView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceHeaderView_Night_0_en.png index e9329548e3..e76102c580 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceHeaderView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceHeaderView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97c8ea5d2d83222ee16c0a27c783e04ec12dbd26aff427c28a21c9c581ad057d -size 60558 +oid sha256:e20d4dc80e8f983516cde0361333f941818cade431fb38ae318cfa9a589ab0d8 +size 60846 From e78a9917e802f0be22b7fdf7bf691225d221b611 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Sep 2025 17:23:55 +0200 Subject: [PATCH 121/145] Add missing preview case (space without name) --- .../android/features/space/impl/SpaceStateProvider.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt index 36c2ab62b0..cf2fcf92b5 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt @@ -18,7 +18,15 @@ open class SpaceStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aSpaceState(), - aSpaceState(hasMoreToLoad = true), + aSpaceState( + parentSpace = aSpaceRoom( + name = null, + numJoinedMembers = 5, + childrenCount = 10, + worldReadable = true, + ), + hasMoreToLoad = true, + ), aSpaceState( hasMoreToLoad = true, children = aListOfSpaceRooms(), From f6cc4bcfa1ca7399942b9cad64c21c153af98932 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Sep 2025 17:53:30 +0200 Subject: [PATCH 122/145] Add missing tests. --- features/joinroom/impl/build.gradle.kts | 1 + .../joinroom/impl/JoinRoomPresenterTest.kt | 133 ++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/features/joinroom/impl/build.gradle.kts b/features/joinroom/impl/build.gradle.kts index 731a8b3377..476aacd863 100644 --- a/features/joinroom/impl/build.gradle.kts +++ b/features/joinroom/impl/build.gradle.kts @@ -43,4 +43,5 @@ dependencies { testImplementation(projects.features.invite.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.preferences.test) + testImplementation(projects.libraries.previewutils) } 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 9d4b16c1f3..574c310d1f 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 @@ -50,8 +50,10 @@ import io.element.android.libraries.matrix.test.room.aRoomPreviewInfo import io.element.android.libraries.matrix.test.room.join.FakeJoinRoom import io.element.android.libraries.matrix.test.spaces.FakeSpaceRoomList import io.element.android.libraries.matrix.test.spaces.FakeSpaceService +import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.matrix.ui.model.InviteSender import io.element.android.libraries.matrix.ui.model.toInviteSender +import io.element.android.libraries.previewutils.room.aSpaceRoom import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.any import io.element.android.tests.testutils.lambda.assert @@ -189,6 +191,137 @@ class JoinRoomPresenterTest { } } + @Test + fun `present - when space is invited then join authorization is equal to invited, an inviter is provided`() = runTest { + val inviter = aRoomMember(userId = A_USER_ID_2, displayName = "Bob") + val expectedInviteSender = inviter.toInviteSender() + val spaceHero = aMatrixUser() + val roomInfo = aRoomInfo( + isSpace = true, + currentUserMembership = CurrentUserMembership.INVITED, + joinedMembersCount = 5, + inviter = inviter, + heroes = listOf(spaceHero), + ) + val inviteData = roomInfo.toInviteData() + val matrixClient = FakeMatrixClient( + getNotJoinedRoomResult = { _, _ -> + Result.success( + aRoomPreview( + info = aRoomPreviewInfo( + numberOfJoinedMembers = 5, + ), + roomMembershipDetails = { + Result.success(aRoomMembershipDetails()) + }, + ) + ) + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { + FakeSpaceRoomList( + initialSpaceFlowValue = aSpaceRoom( + childrenCount = 3, + ) + ) + }, + ), + ).apply { + getRoomInfoFlowLambda = { _ -> + flowOf(Optional.of(roomInfo)) + } + } + val presenter = createJoinRoomPresenter( + matrixClient = matrixClient + ) + presenter.test { + skipItems(2) + awaitItem().also { state -> + assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.IsInvited(inviteData, expectedInviteSender)) + assertThat((state.contentState as ContentState.Loaded).numberOfMembers).isEqualTo(5) + // Space details are provided + assertThat(state.contentState.details).isEqualTo( + LoadedDetails.Space( + childrenCount = 3, + heroes = persistentListOf(spaceHero), + ) + ) + } + } + } + + @Test + fun `present - space is invited - no room info`() = runTest { + val spaceHero = aMatrixUser() + val spaceRoom = aSpaceRoom( + childrenCount = 3, + heroes = listOf(spaceHero), + ) + val matrixClient = FakeMatrixClient( + getNotJoinedRoomResult = { _, _ -> + Result.failure(Exception("Error")) + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { + FakeSpaceRoomList( + initialSpaceFlowValue = spaceRoom, + ) + }, + ), + ).apply { + getRoomInfoFlowLambda = { _ -> + flowOf(Optional.ofNullable(null)) + } + } + val presenter = createJoinRoomPresenter( + matrixClient = matrixClient + ) + presenter.test { + skipItems(1) + awaitItem().also { state -> + // Space details are provided + assertThat((state.contentState as ContentState.Loaded).details).isEqualTo( + LoadedDetails.Space( + childrenCount = 3, + heroes = persistentListOf(spaceHero), + ) + ) + } + } + } + + @Test + fun `present - space is invited - no room info - space room state set`() = runTest { + val spaceRoom = aSpaceRoom( + state = CurrentUserMembership.INVITED, + ) + val matrixClient = FakeMatrixClient( + getNotJoinedRoomResult = { _, _ -> + Result.failure(Exception("Error")) + }, + spaceService = FakeSpaceService( + spaceRoomListResult = { + FakeSpaceRoomList( + initialSpaceFlowValue = spaceRoom, + ) + }, + ), + ).apply { + getRoomInfoFlowLambda = { _ -> + flowOf(Optional.ofNullable(null)) + } + } + val presenter = createJoinRoomPresenter( + matrixClient = matrixClient + ) + presenter.test { + awaitItem().also { state -> + // Space details are provided + assertThat(state.contentState).isInstanceOf(ContentState.Loading::class.java) + } + } + } + @Test fun `present - when room is invited read the number of member from the room preview`() = runTest { val roomInfo = aRoomInfo( From fa14e4c1067c2aaa3035817ce6af63cc33306bd0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Sep 2025 20:12:26 +0200 Subject: [PATCH 123/145] Add notification troubleshoot test about blocked users. --- .../preferences/impl/PreferencesFlowNode.kt | 4 + libraries/permissions/impl/build.gradle.kts | 1 + ...ficationTroubleshootCheckPermissionTest.kt | 6 +- ...tionTroubleshootCheckPermissionTestTest.kt | 3 +- libraries/push/impl/build.gradle.kts | 1 + .../impl/troubleshoot/IgnoredUsersTest.kt | 69 ++++++++++++++ .../impl/troubleshoot/PushLoopbackTest.kt | 6 +- .../impl/src/main/res/values/localazy.xml | 8 ++ .../impl/troubleshoot/IgnoredUsersTestTest.kt | 93 +++++++++++++++++++ .../impl/troubleshoot/PushLoopbackTestTest.kt | 3 +- .../pushproviders/firebase/build.gradle.kts | 1 + .../troubleshoot/FirebaseTokenTest.kt | 6 +- .../troubleshoot/FirebaseTokenTestTest.kt | 3 +- .../unifiedpush/build.gradle.kts | 1 + .../troubleshoot/UnifiedPushTest.kt | 6 +- .../troubleshoot/UnifiedPushTestTest.kt | 3 +- .../api/NotificationTroubleShootEntryPoint.kt | 1 + .../test/NotificationTroubleshootNavigator.kt | 12 +++ .../api/test/NotificationTroubleshootTest.kt | 5 +- .../test/NotificationTroubleshootTestState.kt | 6 +- .../impl/TroubleshootNotificationsNode.kt | 16 +++- .../TroubleshootNotificationsPresenter.kt | 15 ++- .../TroubleshootNotificationsStateProvider.kt | 19 +++- .../impl/TroubleshootNotificationsView.kt | 18 ++-- .../impl/TroubleshootTestSuite.kt | 11 ++- ...tNotificationTroubleShootEntryPointTest.kt | 3 +- .../impl/FakeNotificationTroubleshootTest.kt | 6 +- .../TroubleshootNotificationsPresenterTest.kt | 6 ++ libraries/troubleshoot/test/build.gradle.kts | 18 ++++ .../FakeNotificationTroubleshootNavigator.kt | 17 ++++ tools/localazy/config.json | 1 + 31 files changed, 338 insertions(+), 30 deletions(-) create mode 100644 libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTest.kt create mode 100644 libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTestTest.kt create mode 100644 libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootNavigator.kt create mode 100644 libraries/troubleshoot/test/build.gradle.kts create mode 100644 libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/FakeNotificationTroubleshootNavigator.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index 57643e3931..49e297af08 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -208,6 +208,10 @@ class PreferencesFlowNode( navigateUp() } } + + override fun openIgnoredUsers() { + backstack.push(NavTarget.BlockedUsers) + } }) .build() } diff --git a/libraries/permissions/impl/build.gradle.kts b/libraries/permissions/impl/build.gradle.kts index f7811c649d..a4fafda599 100644 --- a/libraries/permissions/impl/build.gradle.kts +++ b/libraries/permissions/impl/build.gradle.kts @@ -43,5 +43,6 @@ dependencies { testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.permissions.test) + testImplementation(projects.libraries.troubleshoot.test) testImplementation(projects.services.toolbox.test) } diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTest.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTest.kt index 19cedab019..eeadb5598c 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTest.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTest.kt @@ -15,6 +15,7 @@ import dev.zacsweers.metro.Inject import io.element.android.libraries.permissions.api.PermissionStateProvider import io.element.android.libraries.permissions.impl.R import io.element.android.libraries.permissions.impl.action.PermissionActions +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestDelegate import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState @@ -54,7 +55,10 @@ class NotificationTroubleshootCheckPermissionTest( override suspend fun reset() = delegate.reset() - override suspend fun quickFix(coroutineScope: CoroutineScope) { + override suspend fun quickFix( + coroutineScope: CoroutineScope, + navigator: NotificationTroubleshootNavigator, + ) { // Do not bother about asking the permission inline, just lead the user to the settings permissionActions.openSettings() } diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt index a530b8dbee..f6696265bc 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt @@ -13,6 +13,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.libraries.permissions.impl.action.FakePermissionActions import io.element.android.libraries.permissions.test.FakePermissionStateProvider import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState +import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider import io.element.android.services.toolbox.test.strings.FakeStringProvider import kotlinx.coroutines.launch @@ -84,7 +85,7 @@ class NotificationTroubleshootCheckPermissionTestTest { assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) // Quick fix launch { - sut.quickFix(this) + sut.quickFix(this, FakeNotificationTroubleshootNavigator()) // Run the test again (IRL it will be done thanks to the resuming of the application) sut.run(this) } diff --git a/libraries/push/impl/build.gradle.kts b/libraries/push/impl/build.gradle.kts index 3e186d31da..fa0f65cb8f 100644 --- a/libraries/push/impl/build.gradle.kts +++ b/libraries/push/impl/build.gradle.kts @@ -72,6 +72,7 @@ dependencies { testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushproviders.test) testImplementation(projects.libraries.pushstore.test) + testImplementation(projects.libraries.troubleshoot.test) testImplementation(projects.features.call.test) testImplementation(projects.features.lockscreen.test) testImplementation(projects.services.appnavstate.test) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTest.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTest.kt new file mode 100644 index 0000000000..93e855c94d --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTest.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.push.impl.troubleshoot + +import dev.zacsweers.metro.ContributesIntoSet +import dev.zacsweers.metro.Inject +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.push.impl.R +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestDelegate +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState +import io.element.android.services.toolbox.api.strings.StringProvider +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.StateFlow + +@ContributesIntoSet(SessionScope::class) +@Inject +class IgnoredUsersTest( + private val matrixClient: MatrixClient, + private val stringProvider: StringProvider, +) : NotificationTroubleshootTest { + override val order = 80 + private val delegate = NotificationTroubleshootTestDelegate( + defaultName = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_title), + defaultDescription = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_description), + fakeDelay = NotificationTroubleshootTestDelegate.SHORT_DELAY, + ) + override val state: StateFlow = delegate.state + + override suspend fun run(coroutineScope: CoroutineScope) { + delegate.start() + val ignorerUsers = matrixClient.ignoredUsersFlow.value + if (ignorerUsers.isEmpty()) { + delegate.updateState( + description = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_result_none), + status = NotificationTroubleshootTestState.Status.Success, + ) + } else { + delegate.updateState( + description = stringProvider.getQuantityString( + R.plurals.troubleshoot_notifications_test_blocked_users_result_some, + ignorerUsers.size, + ignorerUsers.size + ), + status = NotificationTroubleshootTestState.Status.Failure( + hasQuickFix = true, + isCritical = false, + quickFixButtonString = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_quick_fix), + ), + ) + } + } + + override suspend fun quickFix( + coroutineScope: CoroutineScope, + navigator: NotificationTroubleshootNavigator, + ) { + navigator.openIgnoredUsers() + } + + override suspend fun reset() = delegate.reset() +} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt index fede1a7099..3845b68b18 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt @@ -13,6 +13,7 @@ import dev.zacsweers.metro.Inject import io.element.android.libraries.push.api.PushService import io.element.android.libraries.push.api.gateway.PushGatewayFailure import io.element.android.libraries.push.impl.R +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestDelegate import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState @@ -99,7 +100,10 @@ class PushLoopbackTest( ) } - override suspend fun quickFix(coroutineScope: CoroutineScope) { + override suspend fun quickFix( + coroutineScope: CoroutineScope, + navigator: NotificationTroubleshootNavigator, + ) { delegate.start() pushService.getCurrentPushProvider()?.rotateToken() run(coroutineScope) diff --git a/libraries/push/impl/src/main/res/values/localazy.xml b/libraries/push/impl/src/main/res/values/localazy.xml index 069183a3a2..8e9da34b73 100644 --- a/libraries/push/impl/src/main/res/values/localazy.xml +++ b/libraries/push/impl/src/main/res/values/localazy.xml @@ -54,6 +54,14 @@ "Background synchronization" "Google Services" "No valid Google Play Services found. Notifications may not work properly." + "Checking blocked users" + "View blocked users" + "No users are blocked." + + "You blocked %1$d user. You will not receive notifications for this user." + "You blocked %1$d users. You will not receive notifications for these users." + + "Blocked users" "Get the name of the current provider." "No push providers selected." "Current push provider: %1$s." diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTestTest.kt new file mode 100644 index 0000000000..ed1cf93fce --- /dev/null +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTestTest.kt @@ -0,0 +1,93 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.push.impl.troubleshoot + +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +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.FakeMatrixClient +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState +import io.element.android.services.toolbox.test.strings.FakeStringProvider +import io.element.android.tests.testutils.lambda.lambdaRecorder +import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class IgnoredUsersTestTest { + @Test + fun `test IgnoredUsersTest order`() = runTest { + val sut = IgnoredUsersTest( + matrixClient = FakeMatrixClient(), + stringProvider = FakeStringProvider(), + ) + assertThat(sut.order).isEqualTo(80) + } + + @Test + fun `test IgnoredUsersTest quick fix`() = runTest { + val sut = IgnoredUsersTest( + matrixClient = FakeMatrixClient(), + stringProvider = FakeStringProvider(), + ) + val openIgnoredUsersResult = lambdaRecorder {} + val navigator = object : NotificationTroubleshootNavigator { + override fun openIgnoredUsers() = openIgnoredUsersResult() + } + sut.quickFix( + coroutineScope = backgroundScope, + navigator = navigator, + ) + openIgnoredUsersResult.assertions().isCalledOnce() + } + + @Test + fun `test IgnoredUsersTest with no blocked users`() = runTest { + val sut = IgnoredUsersTest( + matrixClient = FakeMatrixClient( + ignoredUsersFlow = MutableStateFlow(persistentListOf()) + ), + stringProvider = FakeStringProvider(), + ) + backgroundScope.launch { + sut.run(this) + } + sut.state.test { + assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) + assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) + val lastItem = awaitItem() + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Success) + } + } + + @Test + fun `test IgnoredUsersTest with blocked users`() = runTest { + val sut = IgnoredUsersTest( + matrixClient = FakeMatrixClient( + ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID, A_USER_ID_2)) + ), + stringProvider = FakeStringProvider(), + ) + backgroundScope.launch { + sut.run(this) + } + sut.state.test { + assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) + assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) + val lastItem = awaitItem() + val lastStatus = lastItem.status as NotificationTroubleshootTestState.Status.Failure + assertThat(lastStatus.hasQuickFix).isTrue() + assertThat(lastStatus.isCritical).isFalse() + assertThat(lastStatus.quickFixButtonString).isNotNull() + assertThat(lastItem.description).contains("2") + } + } +} diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt index e4fa26a28b..182ffd89a8 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt @@ -15,6 +15,7 @@ import io.element.android.libraries.push.api.gateway.PushGatewayFailure import io.element.android.libraries.push.test.FakePushService import io.element.android.libraries.pushproviders.test.FakePushProvider import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState +import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.lambda.lambdaRecorder @@ -97,7 +98,7 @@ class PushLoopbackTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) - sut.quickFix(this) + sut.quickFix(this, FakeNotificationTroubleshootNavigator()) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) rotateTokenLambda.assertions().isCalledOnce() diff --git a/libraries/pushproviders/firebase/build.gradle.kts b/libraries/pushproviders/firebase/build.gradle.kts index acb12ae150..05e60920e5 100644 --- a/libraries/pushproviders/firebase/build.gradle.kts +++ b/libraries/pushproviders/firebase/build.gradle.kts @@ -76,5 +76,6 @@ dependencies { testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushstore.test) testImplementation(projects.libraries.sessionStorage.test) + testImplementation(projects.libraries.troubleshoot.test) testImplementation(projects.services.toolbox.test) } diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt index 2d6ec699da..ae70114971 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt @@ -14,6 +14,7 @@ import io.element.android.libraries.pushproviders.firebase.FirebaseConfig import io.element.android.libraries.pushproviders.firebase.FirebaseStore import io.element.android.libraries.pushproviders.firebase.FirebaseTroubleshooter import io.element.android.libraries.pushproviders.firebase.R +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestDelegate import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState @@ -71,7 +72,10 @@ class FirebaseTokenTest( override suspend fun reset() = delegate.reset() - override suspend fun quickFix(coroutineScope: CoroutineScope) { + override suspend fun quickFix( + coroutineScope: CoroutineScope, + navigator: NotificationTroubleshootNavigator, + ) { delegate.start() firebaseTroubleshooter.troubleshoot() run(coroutineScope) diff --git a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt index b66f094d76..b7a39feb9f 100644 --- a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt +++ b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt @@ -14,6 +14,7 @@ import io.element.android.libraries.pushproviders.firebase.FirebaseConfig import io.element.android.libraries.pushproviders.firebase.InMemoryFirebaseStore import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.libraries.troubleshoot.api.test.TestFilterData +import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator import io.element.android.services.toolbox.test.strings.FakeStringProvider import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest @@ -62,7 +63,7 @@ class FirebaseTokenTestTest { val lastItem = awaitItem() assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) // Quick fix - sut.quickFix(this) + sut.quickFix(this, FakeNotificationTroubleshootNavigator()) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Success) } diff --git a/libraries/pushproviders/unifiedpush/build.gradle.kts b/libraries/pushproviders/unifiedpush/build.gradle.kts index c2ec6b3d1c..e416ccf8bf 100644 --- a/libraries/pushproviders/unifiedpush/build.gradle.kts +++ b/libraries/pushproviders/unifiedpush/build.gradle.kts @@ -51,6 +51,7 @@ dependencies { testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushproviders.test) testImplementation(projects.libraries.pushstore.test) + testImplementation(projects.libraries.troubleshoot.test) testImplementation(projects.services.toolbox.test) testImplementation(projects.services.appnavstate.test) } diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTest.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTest.kt index 40f8115fd6..6791a901db 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTest.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTest.kt @@ -13,6 +13,7 @@ import dev.zacsweers.metro.Inject import io.element.android.libraries.pushproviders.unifiedpush.R import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushConfig import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushDistributorProvider +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestDelegate import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState @@ -64,7 +65,10 @@ class UnifiedPushTest( override suspend fun reset() = delegate.reset() - override suspend fun quickFix(coroutineScope: CoroutineScope) { + override suspend fun quickFix( + coroutineScope: CoroutineScope, + navigator: NotificationTroubleshootNavigator, + ) { openDistributorWebPageAction.execute() } } diff --git a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt index 7b9059a324..53d85c7fea 100644 --- a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt +++ b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.pushproviders.api.Distributor import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushConfig import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.libraries.troubleshoot.api.test.TestFilterData +import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator import io.element.android.services.toolbox.test.strings.FakeStringProvider import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest @@ -67,7 +68,7 @@ class UnifiedPushTestTest { assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) // Quick fix launch { - sut.quickFix(this) + sut.quickFix(this, FakeNotificationTroubleshootNavigator()) sut.run(this) } assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) diff --git a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/NotificationTroubleShootEntryPoint.kt b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/NotificationTroubleShootEntryPoint.kt index bc3b019ba3..bf0c6bb883 100644 --- a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/NotificationTroubleShootEntryPoint.kt +++ b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/NotificationTroubleShootEntryPoint.kt @@ -22,5 +22,6 @@ interface NotificationTroubleShootEntryPoint : FeatureEntryPoint { interface Callback : Plugin { fun onDone() + fun openIgnoredUsers() } } diff --git a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootNavigator.kt b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootNavigator.kt new file mode 100644 index 0000000000..0cce358072 --- /dev/null +++ b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootNavigator.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.troubleshoot.api.test + +interface NotificationTroubleshootNavigator { + fun openIgnoredUsers() +} diff --git a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTest.kt b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTest.kt index d20370729e..f729cd3300 100644 --- a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTest.kt +++ b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTest.kt @@ -16,7 +16,10 @@ interface NotificationTroubleshootTest { fun isRelevant(data: TestFilterData): Boolean = true suspend fun run(coroutineScope: CoroutineScope) suspend fun reset() - suspend fun quickFix(coroutineScope: CoroutineScope) { + suspend fun quickFix( + coroutineScope: CoroutineScope, + navigator: NotificationTroubleshootNavigator, + ) { error("Quick fix not implemented, you need to override this method in your test") } } diff --git a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestState.kt b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestState.kt index d845332df3..ffb6d9a26a 100644 --- a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestState.kt +++ b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestState.kt @@ -17,6 +17,10 @@ data class NotificationTroubleshootTestState( data object InProgress : Status data object WaitingForUser : Status data object Success : Status - data class Failure(val hasQuickFix: Boolean) : Status + data class Failure( + val hasQuickFix: Boolean, + val isCritical: Boolean = true, + val quickFixButtonString: String? = null, + ) : Status } } diff --git a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsNode.kt b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsNode.kt index 1d113aee64..fcd9306171 100644 --- a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsNode.kt +++ b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsNode.kt @@ -19,6 +19,7 @@ import im.vector.app.features.analytics.plan.MobileScreen import io.element.android.annotations.ContributesNode import io.element.android.libraries.di.SessionScope import io.element.android.libraries.troubleshoot.api.NotificationTroubleShootEntryPoint +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator import io.element.android.services.analytics.api.ScreenTracker @ContributesNode(SessionScope::class) @@ -26,15 +27,26 @@ import io.element.android.services.analytics.api.ScreenTracker class TroubleshootNotificationsNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val presenter: TroubleshootNotificationsPresenter, private val screenTracker: ScreenTracker, -) : Node(buildContext, plugins = plugins) { + factory: TroubleshootNotificationsPresenter.Factory, +) : Node(buildContext, plugins = plugins), + NotificationTroubleshootNavigator { + private val presenter = factory.create( + navigator = this, + ) + private fun onDone() { plugins().forEach { it.onDone() } } + override fun openIgnoredUsers() { + plugins().forEach { + it.openIgnoredUsers() + } + } + @Composable override fun View(modifier: Modifier) { screenTracker.TrackScreen(MobileScreen.ScreenName.NotificationTroubleshoot) diff --git a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenter.kt b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenter.kt index 753949f71b..b1c3c2d9b9 100644 --- a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenter.kt +++ b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenter.kt @@ -12,14 +12,23 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator import kotlinx.coroutines.launch @Inject class TroubleshootNotificationsPresenter( + @Assisted private val navigator: NotificationTroubleshootNavigator, private val troubleshootTestSuite: TroubleshootTestSuite, ) : Presenter { + @AssistedFactory + fun interface Factory { + fun create(navigator: NotificationTroubleshootNavigator): TroubleshootNotificationsPresenter + } + @Composable override fun present(): TroubleshootNotificationsState { val coroutineScope = rememberCoroutineScope() @@ -34,7 +43,11 @@ class TroubleshootNotificationsPresenter( troubleshootTestSuite.runTestSuite(this) } is TroubleshootNotificationsEvents.QuickFix -> coroutineScope.launch { - troubleshootTestSuite.quickFix(event.testIndex, this) + troubleshootTestSuite.quickFix( + testIndex = event.testIndex, + coroutineScope = this, + navigator = navigator, + ) } TroubleshootNotificationsEvents.RetryFailedTests -> coroutineScope.launch { troubleshootTestSuite.retryFailedTest(this) diff --git a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsStateProvider.kt b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsStateProvider.kt index 4ea9355a8c..8c2708ed9d 100644 --- a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsStateProvider.kt +++ b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsStateProvider.kt @@ -31,8 +31,12 @@ open class TroubleshootNotificationsStateProvider : PreviewParameterProvider Unit, ) { - if ((testState.status as? Status.Idle)?.visible == false) return + val status = testState.status + if ((status as? Status.Idle)?.visible == false) return ListItem( headlineContent = { Text(text = testState.name) }, supportingContent = { Text(text = testState.description) }, - trailingContent = when (testState.status) { + trailingContent = when (status) { is Status.Idle -> null Status.InProgress -> ListItemContent.Custom { CircularProgressIndicator( @@ -98,20 +99,19 @@ private fun ColumnScope.TroubleshootTestView( Icon( contentDescription = null, modifier = Modifier.size(24.dp), - imageVector = CompoundIcons.ErrorSolid(), - tint = ElementTheme.colors.textCriticalPrimary + imageVector = if (status.isCritical) CompoundIcons.ErrorSolid() else CompoundIcons.Warning(), + tint = ElementTheme.colors.iconCriticalPrimary, ) } } ) - if ((testState.status as? Status.Failure)?.hasQuickFix == true) { + if (status is Status.Failure && status.hasQuickFix) { ListItem( - headlineContent = { - }, + headlineContent = { }, trailingContent = ListItemContent.Custom { Button( - text = stringResource(id = R.string.troubleshoot_notifications_screen_quick_fix_action), - onClick = onQuickFixClick + text = status.quickFixButtonString ?: stringResource(id = R.string.troubleshoot_notifications_screen_quick_fix_action), + onClick = onQuickFixClick, ) } ) diff --git a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootTestSuite.kt b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootTestSuite.kt index d0fd005307..c26510fc92 100644 --- a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootTestSuite.kt +++ b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootTestSuite.kt @@ -11,6 +11,7 @@ import dev.zacsweers.metro.Inject import im.vector.app.features.analytics.plan.NotificationTroubleshoot import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.push.api.GetCurrentPushProvider +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.libraries.troubleshoot.api.test.TestFilterData @@ -90,8 +91,12 @@ class TroubleshootTestSuite( ) } - suspend fun quickFix(testIndex: Int, coroutineScope: CoroutineScope) { - tests[testIndex].quickFix(coroutineScope) + suspend fun quickFix( + testIndex: Int, + coroutineScope: CoroutineScope, + navigator: NotificationTroubleshootNavigator, + ) { + tests[testIndex].quickFix(coroutineScope, navigator) } } @@ -104,7 +109,7 @@ fun List.computeMainState(): AsyncAction { if (any { it.status is NotificationTroubleshootTestState.Status.WaitingForUser }) { AsyncAction.ConfirmingNoParams - } else if (any { it.status is NotificationTroubleshootTestState.Status.Failure }) { + } else if (any { it.status.let { status -> status is NotificationTroubleshootTestState.Status.Failure && status.isCritical } }) { AsyncAction.Failure(Exception("Some tests failed")) } else { AsyncAction.Success(Unit) diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt index d9bf607531..e0d817a4ca 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt @@ -28,12 +28,13 @@ class DefaultNotificationTroubleShootEntryPointTest { TroubleshootNotificationsNode( buildContext = buildContext, plugins = plugins, - presenter = createTroubleshootNotificationsPresenter(), + factory = { createTroubleshootNotificationsPresenter() }, screenTracker = FakeScreenTracker(), ) } val callback = object : NotificationTroubleShootEntryPoint.Callback { override fun onDone() = lambdaError() + override fun openIgnoredUsers() = lambdaError() } val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) .callback(callback) diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/FakeNotificationTroubleshootTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/FakeNotificationTroubleshootTest.kt index bfd4025a2a..7fa2e93d85 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/FakeNotificationTroubleshootTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/FakeNotificationTroubleshootTest.kt @@ -7,6 +7,7 @@ package io.element.android.libraries.troubleshoot.impl +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import kotlinx.coroutines.CoroutineScope @@ -50,7 +51,10 @@ class FakeNotificationTroubleshootTest( } } - override suspend fun quickFix(coroutineScope: CoroutineScope) { + override suspend fun quickFix( + coroutineScope: CoroutineScope, + navigator: NotificationTroubleshootNavigator, + ) { updateState(NotificationTroubleshootTestState.Status.InProgress) quickFixAction()?.let { _state.emit(it) diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt index 211fa595b5..a3a32bca46 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt @@ -13,9 +13,11 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.push.test.FakeGetCurrentPushProvider +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.lambda.lambdaError import kotlinx.coroutines.test.runTest import org.junit.Test @@ -111,9 +113,13 @@ private fun createTroubleshootTestSuite( } internal fun createTroubleshootNotificationsPresenter( + navigator: NotificationTroubleshootNavigator = object : NotificationTroubleshootNavigator { + override fun openIgnoredUsers() = lambdaError() + }, troubleshootTestSuite: TroubleshootTestSuite = createTroubleshootTestSuite(), ): TroubleshootNotificationsPresenter { return TroubleshootNotificationsPresenter( + navigator = navigator, troubleshootTestSuite = troubleshootTestSuite, ) } diff --git a/libraries/troubleshoot/test/build.gradle.kts b/libraries/troubleshoot/test/build.gradle.kts new file mode 100644 index 0000000000..664c4e4d1d --- /dev/null +++ b/libraries/troubleshoot/test/build.gradle.kts @@ -0,0 +1,18 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.libraries.troubleshoot.test" +} + +dependencies { + implementation(projects.libraries.troubleshoot.api) + implementation(projects.tests.testutils) +} diff --git a/libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/FakeNotificationTroubleshootNavigator.kt b/libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/FakeNotificationTroubleshootNavigator.kt new file mode 100644 index 0000000000..63445e5a3e --- /dev/null +++ b/libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/FakeNotificationTroubleshootNavigator.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.troubleshoot.test + +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator +import io.element.android.tests.testutils.lambda.lambdaError + +class FakeNotificationTroubleshootNavigator( + private val openIgnoredUsersResult: () -> Unit = { lambdaError() }, +) : NotificationTroubleshootNavigator { + override fun openIgnoredUsers() = openIgnoredUsersResult() +} diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 0aac7e51af..4264b35229 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -123,6 +123,7 @@ "includeRegex" : [ "push_.*", "notification_.*", + "troubleshoot_notifications\\.test_blocked_users\\..*", "troubleshoot_notifications_test_current_push_provider.*", "troubleshoot_notifications_test_detect_push_provider.*", "troubleshoot_notifications_test_display_notification_.*", From a83fc2aa1d2e304a06c48b770692617af91cfb87 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 23 Sep 2025 09:13:45 +0200 Subject: [PATCH 124/145] Add default value for Failure.hasQuickFix --- ...otificationTroubleshootCheckPermissionTestTest.kt | 4 ++-- .../impl/troubleshoot/CurrentPushProviderTest.kt | 2 +- .../push/impl/troubleshoot/NotificationTest.kt | 4 ++-- .../push/impl/troubleshoot/PushLoopbackTest.kt | 8 ++++---- .../push/impl/troubleshoot/PushProvidersTest.kt | 2 +- .../impl/troubleshoot/CurrentPushProviderTestTest.kt | 2 +- .../push/impl/troubleshoot/PushLoopbackTestTest.kt | 12 ++++++------ .../push/impl/troubleshoot/PushProvidersTestTest.kt | 2 +- .../troubleshoot/FirebaseAvailabilityTest.kt | 2 +- .../firebase/troubleshoot/FirebaseTokenTest.kt | 2 +- .../troubleshoot/FirebaseAvailabilityTestTest.kt | 2 +- .../firebase/troubleshoot/FirebaseTokenTestTest.kt | 4 ++-- .../troubleshoot/UnifiedPushMatrixGatewayTest.kt | 6 +++--- .../unifiedpush/troubleshoot/UnifiedPushTest.kt | 2 +- .../troubleshoot/UnifiedPushMatrixGatewayTestTest.kt | 6 +++--- .../unifiedpush/troubleshoot/UnifiedPushTestTest.kt | 4 ++-- .../api/test/NotificationTroubleshootTestDelegate.kt | 2 +- .../api/test/NotificationTroubleshootTestState.kt | 2 +- 18 files changed, 34 insertions(+), 34 deletions(-) diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt index f6696265bc..cbd7c2b8c3 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt @@ -82,7 +82,7 @@ class NotificationTroubleshootCheckPermissionTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) // Quick fix launch { sut.quickFix(this, FakeNotificationTroubleshootNavigator()) @@ -116,7 +116,7 @@ class NotificationTroubleshootCheckPermissionTestTest { sut.state.test { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) - assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) + assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) sut.reset() assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTest.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTest.kt index 779375351b..5033274998 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTest.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTest.kt @@ -44,7 +44,7 @@ class CurrentPushProviderTest( } else { delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_current_push_provider_failure), - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/NotificationTest.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/NotificationTest.kt index c29ff739d9..da390f85f2 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/NotificationTest.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/NotificationTest.kt @@ -54,7 +54,7 @@ class NotificationTest( } else { delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_display_notification_permission_failure), - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) } } @@ -81,7 +81,7 @@ class NotificationTest( notificationDisplayer.dismissDiagnosticNotification() delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_display_notification_failure), - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) } ) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt index 3845b68b18..5b9a9e2fd1 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt @@ -57,7 +57,7 @@ class PushLoopbackTest( val hasQuickFix = pushService.getCurrentPushProvider()?.canRotateToken() == true delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_1), - status = NotificationTroubleshootTestState.Status.Failure(hasQuickFix) + status = NotificationTroubleshootTestState.Status.Failure(hasQuickFix = hasQuickFix) ) job.cancel() return @@ -65,7 +65,7 @@ class PushLoopbackTest( Timber.e(e, "Failed to test push") delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_2, e.message), - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) job.cancel() return @@ -73,7 +73,7 @@ class PushLoopbackTest( if (!testPushResult) { delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_3), - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) job.cancel() return @@ -94,7 +94,7 @@ class PushLoopbackTest( job.cancel() delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_4), - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) } ) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTest.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTest.kt index d173404732..8e4d1db639 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTest.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTest.kt @@ -48,7 +48,7 @@ class PushProvidersTest( } else { delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_detect_push_provider_failure), - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) } } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTestTest.kt index f6485aa7d6..f45a89ff72 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTestTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTestTest.kt @@ -48,7 +48,7 @@ class CurrentPushProviderTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure()) sut.reset() assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt index 182ffd89a8..e32537e748 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt @@ -40,7 +40,7 @@ class PushLoopbackTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure()) } } @@ -64,7 +64,7 @@ class PushLoopbackTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure()) sut.reset() assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) } @@ -97,10 +97,10 @@ class PushLoopbackTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) sut.quickFix(this, FakeNotificationTroubleshootNavigator()) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) - assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) + assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) rotateTokenLambda.assertions().isCalledOnce() } } @@ -123,7 +123,7 @@ class PushLoopbackTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure()) } } @@ -147,7 +147,7 @@ class PushLoopbackTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure()) assertThat(lastItem.description).contains(A_FAILURE_REASON) } } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTestTest.kt index 8947b646a6..b768e68437 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTestTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTestTest.kt @@ -30,7 +30,7 @@ class PushProvidersTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure()) sut.reset() assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) } diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTest.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTest.kt index 5e90dd84b5..c4ffe19db3 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTest.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTest.kt @@ -51,7 +51,7 @@ class FirebaseAvailabilityTest( } else { delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_firebase_availability_failure), - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) } } diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt index ae70114971..a886b5fb77 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt @@ -63,7 +63,7 @@ class FirebaseTokenTest( } else { delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_firebase_token_failure), - status = NotificationTroubleshootTestState.Status.Failure(true) + status = NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true) ) } } diff --git a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTestTest.kt b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTestTest.kt index 86afded560..acb917b60f 100644 --- a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTestTest.kt +++ b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTestTest.kt @@ -49,7 +49,7 @@ class FirebaseAvailabilityTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure()) sut.reset() assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) } diff --git a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt index b7a39feb9f..eb3ae403fb 100644 --- a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt +++ b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt @@ -61,7 +61,7 @@ class FirebaseTokenTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) // Quick fix sut.quickFix(this, FakeNotificationTroubleshootNavigator()) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) @@ -88,7 +88,7 @@ class FirebaseTokenTestTest { sut.state.test { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) - assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) + assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) sut.reset() assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) } diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTest.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTest.kt index b60c1e5fcf..7a22e92222 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTest.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTest.kt @@ -48,7 +48,7 @@ class UnifiedPushMatrixGatewayTest( if (config == null) { delegate.updateState( description = "No current push provider", - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) } else { val gatewayBaseUrl = config.url.removeSuffix("/_matrix/push/v1/notify") @@ -65,13 +65,13 @@ class UnifiedPushMatrixGatewayTest( } else { delegate.updateState( description = "${config.url} is not a Matrix gateway.", - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) } } catch (throwable: Throwable) { delegate.updateState( description = "Fail to check the gateway ${config.url}: ${throwable.localizedMessage}", - status = NotificationTroubleshootTestState.Status.Failure(false) + status = NotificationTroubleshootTestState.Status.Failure() ) } } diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTest.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTest.kt index 6791a901db..bb2c88bcdd 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTest.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTest.kt @@ -58,7 +58,7 @@ class UnifiedPushTest( } else { delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_unified_push_failure), - status = NotificationTroubleshootTestState.Status.Failure(true) + status = NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true) ) } } diff --git a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTestTest.kt b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTestTest.kt index 95cf85af5c..9729e04eb1 100644 --- a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTestTest.kt +++ b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTestTest.kt @@ -55,7 +55,7 @@ class UnifiedPushMatrixGatewayTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure()) } } @@ -72,7 +72,7 @@ class UnifiedPushMatrixGatewayTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure()) // Reset the error sut.reset() assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) @@ -92,7 +92,7 @@ class UnifiedPushMatrixGatewayTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure()) } } diff --git a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt index 53d85c7fea..257be14f6c 100644 --- a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt +++ b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt @@ -65,7 +65,7 @@ class UnifiedPushTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) // Quick fix launch { sut.quickFix(this, FakeNotificationTroubleshootNavigator()) @@ -99,7 +99,7 @@ class UnifiedPushTestTest { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() - assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true)) + assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) sut.reset() assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) } diff --git a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestDelegate.kt b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestDelegate.kt index 561ec60267..830ba74818 100644 --- a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestDelegate.kt +++ b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestDelegate.kt @@ -60,7 +60,7 @@ class NotificationTroubleshootTestDelegate( if (isSuccess) { NotificationTroubleshootTestState.Status.Success } else { - NotificationTroubleshootTestState.Status.Failure(hasQuickFix) + NotificationTroubleshootTestState.Status.Failure(hasQuickFix = hasQuickFix) } ) } diff --git a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestState.kt b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestState.kt index ffb6d9a26a..4069d78cb3 100644 --- a/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestState.kt +++ b/libraries/troubleshoot/api/src/main/kotlin/io/element/android/libraries/troubleshoot/api/test/NotificationTroubleshootTestState.kt @@ -18,7 +18,7 @@ data class NotificationTroubleshootTestState( data object WaitingForUser : Status data object Success : Status data class Failure( - val hasQuickFix: Boolean, + val hasQuickFix: Boolean = false, val isCritical: Boolean = true, val quickFixButtonString: String? = null, ) : Status From 1d82ad394f31c37d973e4265db8a9712a76e5b3e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 23 Sep 2025 09:26:13 +0200 Subject: [PATCH 125/145] Add missing tests on TroubleshootTestSuite --- .../TroubleshootNotificationsPresenterTest.kt | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt index a3a32bca46..8094dad15a 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt @@ -18,6 +18,7 @@ import io.element.android.libraries.troubleshoot.api.test.NotificationTroublesho import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest import org.junit.Test @@ -76,6 +77,80 @@ class TroubleshootNotificationsPresenterTest { } } + @Test + fun `present - critical failed test`() { + `present - check main state`( + tests = setOf( + FakeNotificationTroubleshootTest( + firstStatus = NotificationTroubleshootTestState.Status.Failure(isCritical = true) + ) + ), + expectedIsCritical = true, + expectedMainState = AsyncAction.Failure::class.java, + ) + } + + @Test + fun `present - success and critical failed test`() { + `present - check main state`( + tests = setOf( + FakeNotificationTroubleshootTest( + firstStatus = NotificationTroubleshootTestState.Status.Success + ), + FakeNotificationTroubleshootTest( + firstStatus = NotificationTroubleshootTestState.Status.Failure(isCritical = true) + ), + ), + expectedIsCritical = true, + expectedMainState = AsyncAction.Failure::class.java, + ) + } + + @Test + fun `present - non critical failed test`() { + `present - check main state`( + tests = setOf( + FakeNotificationTroubleshootTest( + firstStatus = NotificationTroubleshootTestState.Status.Failure(isCritical = false) + ) + ), + expectedIsCritical = false, + expectedMainState = AsyncAction.Success::class.java, + ) + } + + @Test + fun `present - waiting for user`() { + `present - check main state`( + tests = setOf( + FakeNotificationTroubleshootTest( + firstStatus = NotificationTroubleshootTestState.Status.WaitingForUser + ) + ), + expectedIsCritical = false, + expectedMainState = AsyncAction.ConfirmingNoParams::class.java, + ) + } + + private fun `present - check main state`( + tests: Set, + expectedIsCritical: Boolean, + expectedMainState: Class>, + ) = runTest { + val troubleshootTestSuite = createTroubleshootTestSuite( + tests = tests + ) + val presenter = createTroubleshootNotificationsPresenter( + troubleshootTestSuite = troubleshootTestSuite, + ) + presenter.test { + skipItems(1) + val initialState = awaitItem() + assertThat(initialState.hasFailedTests).isEqualTo(expectedIsCritical) + assertThat(initialState.testSuiteState.mainState).isInstanceOf(expectedMainState) + } + } + @Test fun `present - quick fix test`() = runTest { val troubleshootTestSuite = createTroubleshootTestSuite( From 8434b504d49859a9abd5d28f631f357ceeb23013 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 23 Sep 2025 09:28:01 +0200 Subject: [PATCH 126/145] Cleanup --- .../TroubleshootNotificationsPresenterTest.kt | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt index 8094dad15a..4d6b338db7 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt @@ -7,9 +7,6 @@ package io.element.android.libraries.troubleshoot.impl -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.architecture.AsyncAction import io.element.android.libraries.push.test.FakeGetCurrentPushProvider @@ -26,9 +23,7 @@ class TroubleshootNotificationsPresenterTest { @Test fun `present - initial state`() = runTest { val presenter = createTroubleshootNotificationsPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.testSuiteState.tests).isEmpty() assertThat(initialState.testSuiteState.mainState).isEqualTo(AsyncAction.Uninitialized) @@ -43,9 +38,7 @@ class TroubleshootNotificationsPresenterTest { val presenter = createTroubleshootNotificationsPresenter( troubleshootTestSuite = troubleshootTestSuite, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink(TroubleshootNotificationsEvents.StartTests) skipItems(1) @@ -66,9 +59,7 @@ class TroubleshootNotificationsPresenterTest { val presenter = createTroubleshootNotificationsPresenter( troubleshootTestSuite = troubleshootTestSuite, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink(TroubleshootNotificationsEvents.RetryFailedTests) skipItems(1) @@ -163,9 +154,7 @@ class TroubleshootNotificationsPresenterTest { val presenter = createTroubleshootNotificationsPresenter( troubleshootTestSuite = troubleshootTestSuite, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.testSuiteState.mainState).isInstanceOf(AsyncAction.Failure::class.java) From 8d5078904aeb7887ac481197b346b65c77c9a304 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 23 Sep 2025 09:45:36 +0200 Subject: [PATCH 127/145] Introduce runAndTestState extension on NotificationTroubleshootTest --- build.gradle.kts | 2 ++ ...tionTroubleshootCheckPermissionTestTest.kt | 24 ++++---------- .../CurrentPushProviderTestTest.kt | 13 ++------ .../impl/troubleshoot/IgnoredUsersTestTest.kt | 13 ++------ .../impl/troubleshoot/NotificationTestTest.kt | 18 +++------- .../impl/troubleshoot/PushLoopbackTestTest.kt | 33 ++++--------------- .../troubleshoot/PushProvidersTestTest.kt | 13 ++------ .../FirebaseAvailabilityTestTest.kt | 13 ++------ .../troubleshoot/FirebaseTokenTestTest.kt | 18 +++------- .../UnifiedPushMatrixGatewayTestTest.kt | 23 +++---------- .../troubleshoot/UnifiedPushTestTest.kt | 19 +++-------- libraries/troubleshoot/test/build.gradle.kts | 3 ++ .../libraries/troubleshoot/test/Utils.kt | 25 ++++++++++++++ 13 files changed, 73 insertions(+), 144 deletions(-) create mode 100644 libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/Utils.kt diff --git a/build.gradle.kts b/build.gradle.kts index b4ebcf6268..7171d5b079 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,6 +93,8 @@ allprojects { // Fix compilation warning for annotations // See https://youtrack.jetbrains.com/issue/KT-73255/Change-defaulting-rule-for-annotations for more details freeCompilerArgs.add("-Xannotation-default-target=first-only") + // Opt-in to context receivers + freeCompilerArgs.add("-Xcontext-parameters") } } } diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt index cbd7c2b8c3..41a7260ca2 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt @@ -8,12 +8,12 @@ package io.element.android.libraries.permissions.impl.troubleshoot import android.os.Build -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.permissions.impl.action.FakePermissionActions import io.element.android.libraries.permissions.test.FakePermissionStateProvider import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator +import io.element.android.libraries.troubleshoot.test.runAndTestState import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider import io.element.android.services.toolbox.test.strings.FakeStringProvider import kotlinx.coroutines.launch @@ -29,10 +29,7 @@ class NotificationTroubleshootCheckPermissionTestTest { permissionActions = FakePermissionActions(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -48,10 +45,7 @@ class NotificationTroubleshootCheckPermissionTestTest { permissionActions = FakePermissionActions(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -75,16 +69,13 @@ class NotificationTroubleshootCheckPermissionTestTest { permissionActions = actions, stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) // Quick fix - launch { + backgroundScope.launch { sut.quickFix(this, FakeNotificationTroubleshootNavigator()) // Run the test again (IRL it will be done thanks to the resuming of the application) sut.run(this) @@ -110,10 +101,7 @@ class NotificationTroubleshootCheckPermissionTestTest { permissionActions = actions, stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTestTest.kt index f45a89ff72..95bfced7de 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTestTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/CurrentPushProviderTestTest.kt @@ -7,12 +7,11 @@ package io.element.android.libraries.push.impl.troubleshoot -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.push.test.FakeGetCurrentPushProvider import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState +import io.element.android.libraries.troubleshoot.test.runAndTestState import io.element.android.services.toolbox.test.strings.FakeStringProvider -import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import org.junit.Test @@ -23,10 +22,7 @@ class CurrentPushProviderTestTest { getCurrentPushProvider = FakeGetCurrentPushProvider("foo"), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -41,10 +37,7 @@ class CurrentPushProviderTestTest { getCurrentPushProvider = FakeGetCurrentPushProvider(null), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTestTest.kt index ed1cf93fce..e38baa7321 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTestTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/IgnoredUsersTestTest.kt @@ -7,18 +7,17 @@ package io.element.android.libraries.push.impl.troubleshoot -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat 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.FakeMatrixClient import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState +import io.element.android.libraries.troubleshoot.test.runAndTestState import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import org.junit.Test @@ -57,10 +56,7 @@ class IgnoredUsersTestTest { ), stringProvider = FakeStringProvider(), ) - backgroundScope.launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -76,10 +72,7 @@ class IgnoredUsersTestTest { ), stringProvider = FakeStringProvider(), ) - backgroundScope.launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/NotificationTestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/NotificationTestTest.kt index 2c0dbeff10..eecb3801fd 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/NotificationTestTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/NotificationTestTest.kt @@ -7,14 +7,13 @@ package io.element.android.libraries.push.impl.troubleshoot -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDisplayer import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState +import io.element.android.libraries.troubleshoot.test.runAndTestState import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.tests.testutils.lambda.lambdaRecorder -import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import org.junit.Test @@ -31,10 +30,7 @@ class NotificationTestTest { fun `test NotificationTest notification cannot be displayed`() = runTest { fakeNotificationDisplayer.displayDiagnosticNotificationResult = lambdaRecorder { _ -> false } val sut = createNotificationTest() - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) assertThat(awaitItem().status).isInstanceOf(NotificationTroubleshootTestState.Status.Failure::class.java) @@ -44,10 +40,7 @@ class NotificationTestTest { @Test fun `test NotificationTest user does not click on notification`() = runTest { val sut = createNotificationTest() - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.WaitingForUser) @@ -60,10 +53,7 @@ class NotificationTestTest { @Test fun `test NotificationTest user clicks on notification`() = runTest { val sut = createNotificationTest() - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.WaitingForUser) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt index e32537e748..f06b6a9e1b 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt @@ -7,7 +7,6 @@ package io.element.android.libraries.push.impl.troubleshoot -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_FAILURE_REASON @@ -16,10 +15,10 @@ import io.element.android.libraries.push.test.FakePushService import io.element.android.libraries.pushproviders.test.FakePushProvider import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator +import io.element.android.libraries.troubleshoot.test.runAndTestState import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.lambda.lambdaRecorder -import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import org.junit.Test @@ -33,10 +32,7 @@ class PushLoopbackTestTest { clock = FakeSystemClock(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -57,10 +53,7 @@ class PushLoopbackTestTest { clock = FakeSystemClock(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -90,10 +83,7 @@ class PushLoopbackTestTest { clock = FakeSystemClock(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -116,10 +106,7 @@ class PushLoopbackTestTest { clock = FakeSystemClock(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -140,10 +127,7 @@ class PushLoopbackTestTest { clock = FakeSystemClock(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -164,10 +148,7 @@ class PushLoopbackTestTest { clock = FakeSystemClock(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTestTest.kt index b768e68437..b274f0bdab 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTestTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushProvidersTestTest.kt @@ -7,12 +7,11 @@ package io.element.android.libraries.push.impl.troubleshoot -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.pushproviders.test.FakePushProvider import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState +import io.element.android.libraries.troubleshoot.test.runAndTestState import io.element.android.services.toolbox.test.strings.FakeStringProvider -import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import org.junit.Test @@ -23,10 +22,7 @@ class PushProvidersTestTest { pushProviders = emptySet(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -45,10 +41,7 @@ class PushProvidersTestTest { ), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() diff --git a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTestTest.kt b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTestTest.kt index acb917b60f..ce617799f5 100644 --- a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTestTest.kt +++ b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseAvailabilityTestTest.kt @@ -7,14 +7,13 @@ package io.element.android.libraries.pushproviders.firebase.troubleshoot -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.pushproviders.firebase.FakeIsPlayServiceAvailable import io.element.android.libraries.pushproviders.firebase.FirebaseConfig import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.libraries.troubleshoot.api.test.TestFilterData +import io.element.android.libraries.troubleshoot.test.runAndTestState import io.element.android.services.toolbox.test.strings.FakeStringProvider -import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import org.junit.Test @@ -25,10 +24,7 @@ class FirebaseAvailabilityTestTest { isPlayServiceAvailable = FakeIsPlayServiceAvailable(true), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -42,10 +38,7 @@ class FirebaseAvailabilityTestTest { isPlayServiceAvailable = FakeIsPlayServiceAvailable(false), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() diff --git a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt index eb3ae403fb..7e6981ef57 100644 --- a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt +++ b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTestTest.kt @@ -7,7 +7,6 @@ package io.element.android.libraries.pushproviders.firebase.troubleshoot -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.pushproviders.firebase.FakeFirebaseTroubleshooter import io.element.android.libraries.pushproviders.firebase.FirebaseConfig @@ -15,8 +14,8 @@ import io.element.android.libraries.pushproviders.firebase.InMemoryFirebaseStore import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.libraries.troubleshoot.api.test.TestFilterData import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator +import io.element.android.libraries.troubleshoot.test.runAndTestState import io.element.android.services.toolbox.test.strings.FakeStringProvider -import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import org.junit.Test @@ -28,10 +27,7 @@ class FirebaseTokenTestTest { firebaseTroubleshooter = FakeFirebaseTroubleshooter(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -54,10 +50,7 @@ class FirebaseTokenTestTest { ), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -82,10 +75,7 @@ class FirebaseTokenTestTest { ), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) diff --git a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTestTest.kt b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTestTest.kt index 9729e04eb1..f4a0cf5da4 100644 --- a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTestTest.kt +++ b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushMatrixGatewayTestTest.kt @@ -7,7 +7,6 @@ package io.element.android.libraries.pushproviders.unifiedpush.troubleshoot -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig import io.element.android.libraries.pushproviders.test.aCurrentUserPushConfig @@ -18,8 +17,8 @@ import io.element.android.libraries.pushproviders.unifiedpush.matrixDiscoveryRes import io.element.android.libraries.pushproviders.unifiedpush.network.DiscoveryResponse import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.libraries.troubleshoot.api.test.TestFilterData +import io.element.android.libraries.troubleshoot.test.runAndTestState import io.element.android.tests.testutils.testCoroutineDispatchers -import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test @@ -31,10 +30,7 @@ class UnifiedPushMatrixGatewayTestTest { currentUserPushConfig = aCurrentUserPushConfig(), discoveryResponse = matrixDiscoveryResponse, ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -48,10 +44,7 @@ class UnifiedPushMatrixGatewayTestTest { currentUserPushConfig = null, discoveryResponse = matrixDiscoveryResponse, ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -65,10 +58,7 @@ class UnifiedPushMatrixGatewayTestTest { currentUserPushConfig = aCurrentUserPushConfig(), discoveryResponse = invalidDiscoveryResponse, ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -85,10 +75,7 @@ class UnifiedPushMatrixGatewayTestTest { currentUserPushConfig = aCurrentUserPushConfig(), discoveryResponse = { error("Network error") }, ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() diff --git a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt index 257be14f6c..28ab0186da 100644 --- a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt +++ b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/troubleshoot/UnifiedPushTestTest.kt @@ -7,13 +7,13 @@ package io.element.android.libraries.pushproviders.unifiedpush.troubleshoot -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.pushproviders.api.Distributor import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushConfig import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState import io.element.android.libraries.troubleshoot.api.test.TestFilterData import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator +import io.element.android.libraries.troubleshoot.test.runAndTestState import io.element.android.services.toolbox.test.strings.FakeStringProvider import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest @@ -31,10 +31,7 @@ class UnifiedPushTestTest { openDistributorWebPageAction = FakeOpenDistributorWebPageAction(), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() @@ -58,16 +55,13 @@ class UnifiedPushTestTest { ), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)) // Quick fix - launch { + backgroundScope.launch { sut.quickFix(this, FakeNotificationTroubleshootNavigator()) sut.run(this) } @@ -92,10 +86,7 @@ class UnifiedPushTestTest { ), stringProvider = FakeStringProvider(), ) - launch { - sut.run(this) - } - sut.state.test { + sut.runAndTestState { assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false)) assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress) val lastItem = awaitItem() diff --git a/libraries/troubleshoot/test/build.gradle.kts b/libraries/troubleshoot/test/build.gradle.kts index 664c4e4d1d..8321ea5b4f 100644 --- a/libraries/troubleshoot/test/build.gradle.kts +++ b/libraries/troubleshoot/test/build.gradle.kts @@ -15,4 +15,7 @@ android { dependencies { implementation(projects.libraries.troubleshoot.api) implementation(projects.tests.testutils) + implementation(libs.coroutines.test) + implementation(libs.test.core) + implementation(libs.test.turbine) } diff --git a/libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/Utils.kt b/libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/Utils.kt new file mode 100644 index 0000000000..2a8ce30f47 --- /dev/null +++ b/libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/Utils.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.troubleshoot.test + +import app.cash.turbine.TurbineTestContext +import app.cash.turbine.test +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest +import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.TestScope + +context(testScope: TestScope) +suspend fun NotificationTroubleshootTest.runAndTestState( + validate: suspend TurbineTestContext.() -> Unit, +) { + testScope.backgroundScope.launch { + run(this) + } + state.test(validate = validate) +} From 2884ae0f44f4b4a1b77d767fc63e5776dd18c835 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 23 Sep 2025 10:10:44 +0200 Subject: [PATCH 128/145] Detekt and ktlint are confused with Kotlin context... --- libraries/troubleshoot/test/build.gradle.kts | 10 ++++++++++ .../android/libraries/troubleshoot/test/Utils.kt | 2 ++ 2 files changed, 12 insertions(+) diff --git a/libraries/troubleshoot/test/build.gradle.kts b/libraries/troubleshoot/test/build.gradle.kts index 8321ea5b4f..830eb5d6b0 100644 --- a/libraries/troubleshoot/test/build.gradle.kts +++ b/libraries/troubleshoot/test/build.gradle.kts @@ -19,3 +19,13 @@ dependencies { implementation(libs.test.core) implementation(libs.test.turbine) } + +ktlint { + filter { + exclude { element -> + val path = element.file.path + // Exclude this file, that ktlint cannot parse. + path.contains("libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/Utils.kt") + } + } +} diff --git a/libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/Utils.kt b/libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/Utils.kt index 2a8ce30f47..77034da584 100644 --- a/libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/Utils.kt +++ b/libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/Utils.kt @@ -5,6 +5,8 @@ * Please see LICENSE files in the repository root for full details. */ +@file:Suppress("UnusedImports") + package io.element.android.libraries.troubleshoot.test import app.cash.turbine.TurbineTestContext From 46d528e207c178ebfe9d1f375e8bc7bd972a9775 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 23 Sep 2025 08:38:58 +0000 Subject: [PATCH 129/145] Update screenshots --- ...oubleshoot.impl_TroubleshootNotificationsView_Day_2_en.png | 4 ++-- ...bleshoot.impl_TroubleshootNotificationsView_Night_2_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en.png index 22eaaced82..2442a17143 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:642e972ecba4cf6af7961066a67b556047d0ab3c35a4ce66e043ba185d93b528 -size 20101 +oid sha256:9051334b3879fe2a6fb56a3c573ecb49eca7700a94184d828e2c0329cbb82b4b +size 25070 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en.png index 5b2d1f6f65..40126799db 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26e11efbeec28f03e9b8d0df822e886b9e420fc523286cc0aa69760f8d5b639c -size 19562 +oid sha256:50fb2b753bdad6a9df4ce2f55a552464e229c7b81be16e0d4f5c8e4e4b3d129b +size 24312 From 0a2bdbd5a8badfe37007fcfe0cac396f33298541 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 23 Sep 2025 14:08:56 +0200 Subject: [PATCH 130/145] Upgrade Element Call embedded dependency to `v0.16.0-rc.4` (#5391) We need this to test some changes in the nightly versions --- 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 cfa6f1f7ff..75dd7ad6da 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -219,7 +219,7 @@ inject = "javax.inject:javax.inject:1" metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.15.0" +element_call_embedded = "io.element.android:element-call-embedded:0.16.0-rc.4" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } From dce9d52054efc951d5dc9932cda474997641074d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 23 Sep 2025 12:20:13 +0000 Subject: [PATCH 131/145] Update dependency org.matrix.rustcomponents:sdk-android to v25.9.23 --- 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 75dd7ad6da..008828e63d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -166,7 +166,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.19" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.9.23" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 532dd0321285797a19225e3042331c974f69a973 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 23 Sep 2025 12:37:03 +0000 Subject: [PATCH 132/145] Update screenshots --- ...res.preferences.impl.root_PreferencesRootViewDark_0_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_1_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_0_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_1_en.png | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png index 3024f2cff8..782a8aba82 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3329563aa6c438335aaadb18cc2767d78eb16c34b616c5e9b14f0d8b66fb032 -size 38106 +oid sha256:b5c95596f8a3e78692c7fa13b95a3491d320e4a89273c61cc22595817bf4e846 +size 38104 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png index a23da63542..d12ebf79be 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7b3d3f464858c9a298461aad3d3a329ac894fbd6206cbc73ec0de16d20e69e3 -size 37946 +oid sha256:7cfb090fcb56f52c935f72ec52659f574aa088a663a991c7cd49688d42001388 +size 37944 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png index fe9ddfe32f..3f96c2234e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f0ba38204b90b53b0b03efabc5dd69200089327c22250e9416d8ee2fd2b94537 -size 38915 +oid sha256:b092653f3c1192c3c2e0f0eb8803d20a0879af6bdcde2d51f6f6d4894ccc7c52 +size 38914 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png index 694ad9d65e..499340fa1e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb9b09711d4538aa350d9c072b31becb223cd2b842d606f405b208e3cc13b77c +oid sha256:78411c84878a5f97b2208b7d688094148fbf88660b1b8fbc0e5fa7b2aebbbf5b size 38968 From 0a5c178fe8783c4a65b9735870b0074569caefd3 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 23 Sep 2025 16:57:50 +0200 Subject: [PATCH 133/145] Add thread decoration with latest event details (#5355) * Add thread decoration with latest event details * Update screenshots --------- Co-authored-by: ElementBot --- .../messages/impl/MessagesPresenter.kt | 6 +- .../impl/actionlist/ActionListPresenter.kt | 3 +- .../impl/timeline/TimelineStateProvider.kt | 4 +- .../timeline/components/MessageEventBubble.kt | 81 ++++---- .../components/TimelineItemEventRow.kt | 183 +++++++++++++++--- .../TimelineItemEventRowWithReplyPreview.kt | 7 +- .../event/TimelineItemContentFactory.kt | 46 ++++- .../event/TimelineItemContentPollFactory.kt | 10 +- ...TimelineItemContentProfileChangeFactory.kt | 7 +- ...imelineItemContentRoomMembershipFactory.kt | 7 +- .../event/TimelineItemContentStateFactory.kt | 7 +- .../event/TimelineItemEventFactory.kt | 29 ++- .../impl/timeline/model/TimelineItem.kt | 10 +- .../DefaultMessageSummaryFormatter.kt | 14 +- .../messagesummary/MessageSummaryFormatter.kt | 6 +- .../messages/impl/MessagesPresenterTest.kt | 6 +- .../actionlist/ActionListPresenterTest.kt | 10 +- .../impl/fixtures/MessageEventFixtures.kt | 4 +- .../fixtures/TimelineItemsFactoryFixtures.kt | 11 +- .../FakeMessageSummaryFormatter.kt | 4 +- .../TimelineItemContentMessageFactoryTest.kt | 2 +- .../groups/TimelineItemGrouperTest.kt | 3 +- .../pollcontent/PollContentStateFactory.kt | 11 +- .../history/model/PollHistoryItemsFactory.kt | 7 +- .../model/DefaultPollContentStateFactory.kt | 14 +- .../FakePollContentStateFactory.kt | 10 +- .../components/avatar/AvatarSize.kt | 1 + .../api/TimelineEventFormatter.kt | 13 +- .../impl/DefaultTimelineEventFormatter.kt | 12 +- ...DefaultBaseRoomLastMessageFormatterTest.kt | 3 +- ...efaultPinnedMessagesBannerFormatterTest.kt | 3 +- .../matrix/api/timeline/item/ThreadSummary.kt | 8 +- .../api/timeline/item/event/EventContent.kt | 2 +- .../timeline/item/event/EventMessageMapper.kt | 2 +- .../item/event/TimelineEventContentMapper.kt | 12 +- .../matrix/test/timeline/TimelineFixture.kt | 2 +- .../reply/InReplyToDetailsProvider.kt | 5 +- .../ui/messages/reply/InReplyToDetailTest.kt | 5 +- .../textcomposer/model/MessageComposerMode.kt | 3 +- ....components_ThreadSummaryView_Day_0_en.png | 3 + ...omponents_ThreadSummaryView_Night_0_en.png | 3 + ...ItemEventRowWithThreadSummary_Day_0_en.png | 4 +- ...emEventRowWithThreadSummary_Night_0_en.png | 4 +- ...omponents.avatar_Avatar_Avatars_100_en.png | 4 +- ...omponents.avatar_Avatar_Avatars_101_en.png | 4 +- ...omponents.avatar_Avatar_Avatars_102_en.png | 4 +- ...omponents.avatar_Avatar_Avatars_103_en.png | 4 +- ...omponents.avatar_Avatar_Avatars_104_en.png | 4 +- ...omponents.avatar_Avatar_Avatars_105_en.png | 3 + ...omponents.avatar_Avatar_Avatars_106_en.png | 3 + ...omponents.avatar_Avatar_Avatars_107_en.png | 3 + ...components.avatar_Avatar_Avatars_45_en.png | 4 +- ...components.avatar_Avatar_Avatars_46_en.png | 4 +- ...components.avatar_Avatar_Avatars_47_en.png | 4 +- ...components.avatar_Avatar_Avatars_48_en.png | 4 +- ...components.avatar_Avatar_Avatars_49_en.png | 4 +- ...components.avatar_Avatar_Avatars_50_en.png | 4 +- ...components.avatar_Avatar_Avatars_51_en.png | 4 +- ...components.avatar_Avatar_Avatars_52_en.png | 4 +- ...components.avatar_Avatar_Avatars_53_en.png | 4 +- ...components.avatar_Avatar_Avatars_54_en.png | 4 +- ...components.avatar_Avatar_Avatars_55_en.png | 4 +- ...components.avatar_Avatar_Avatars_56_en.png | 4 +- ...components.avatar_Avatar_Avatars_57_en.png | 4 +- ...components.avatar_Avatar_Avatars_58_en.png | 4 +- ...components.avatar_Avatar_Avatars_59_en.png | 4 +- ...components.avatar_Avatar_Avatars_60_en.png | 4 +- ...components.avatar_Avatar_Avatars_61_en.png | 4 +- ...components.avatar_Avatar_Avatars_62_en.png | 4 +- ...components.avatar_Avatar_Avatars_63_en.png | 4 +- ...components.avatar_Avatar_Avatars_64_en.png | 4 +- ...components.avatar_Avatar_Avatars_65_en.png | 4 +- ...components.avatar_Avatar_Avatars_66_en.png | 4 +- ...components.avatar_Avatar_Avatars_67_en.png | 4 +- ...components.avatar_Avatar_Avatars_68_en.png | 4 +- ...components.avatar_Avatar_Avatars_69_en.png | 4 +- ...components.avatar_Avatar_Avatars_70_en.png | 4 +- ...components.avatar_Avatar_Avatars_71_en.png | 4 +- ...components.avatar_Avatar_Avatars_72_en.png | 4 +- ...components.avatar_Avatar_Avatars_73_en.png | 4 +- ...components.avatar_Avatar_Avatars_74_en.png | 4 +- ...components.avatar_Avatar_Avatars_75_en.png | 4 +- ...components.avatar_Avatar_Avatars_76_en.png | 4 +- ...components.avatar_Avatar_Avatars_77_en.png | 4 +- ...components.avatar_Avatar_Avatars_78_en.png | 4 +- ...components.avatar_Avatar_Avatars_79_en.png | 4 +- ...components.avatar_Avatar_Avatars_80_en.png | 4 +- ...components.avatar_Avatar_Avatars_81_en.png | 4 +- ...components.avatar_Avatar_Avatars_82_en.png | 4 +- ...components.avatar_Avatar_Avatars_83_en.png | 4 +- ...components.avatar_Avatar_Avatars_84_en.png | 4 +- ...components.avatar_Avatar_Avatars_85_en.png | 4 +- ...components.avatar_Avatar_Avatars_86_en.png | 4 +- ...components.avatar_Avatar_Avatars_87_en.png | 4 +- ...components.avatar_Avatar_Avatars_88_en.png | 4 +- ...components.avatar_Avatar_Avatars_89_en.png | 4 +- ...components.avatar_Avatar_Avatars_90_en.png | 4 +- ...components.avatar_Avatar_Avatars_91_en.png | 4 +- ...components.avatar_Avatar_Avatars_92_en.png | 4 +- ...components.avatar_Avatar_Avatars_93_en.png | 4 +- ...components.avatar_Avatar_Avatars_94_en.png | 4 +- ...components.avatar_Avatar_Avatars_95_en.png | 4 +- ...components.avatar_Avatar_Avatars_96_en.png | 4 +- ...components.avatar_Avatar_Avatars_97_en.png | 4 +- ...components.avatar_Avatar_Avatars_98_en.png | 4 +- ...components.avatar_Avatar_Avatars_99_en.png | 4 +- 106 files changed, 554 insertions(+), 282 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png 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 1d576472a3..04a456d71b 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 @@ -43,6 +43,7 @@ import io.element.android.features.messages.impl.timeline.components.customreact import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetState import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContentWithAttachment import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent @@ -328,7 +329,10 @@ class MessagesPresenter( val displayThreads = featureFlagService.isFeatureEnabled(FeatureFlags.Threads) if (displayThreads) { // Get either the thread id this event is in, or the event id if it's not in a thread so we can start one - val threadId = targetEvent.threadInfo.threadRootId ?: targetEvent.eventId!!.toThreadId() + val threadId = when (targetEvent.threadInfo) { + is TimelineItemThreadInfo.ThreadResponse -> targetEvent.threadInfo.threadRootId + is TimelineItemThreadInfo.ThreadRoot, null -> targetEvent.eventId?.toThreadId() + } ?: return@launch navigator.onOpenThread(threadId, null) } else { handleActionReply(targetEvent, composerState, timelineProtectionState) 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 a0b8db9979..20dc45ccc8 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 @@ -25,6 +25,7 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContentWithAttachment import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent @@ -174,7 +175,7 @@ class DefaultActionListPresenter( add(TimelineItemAction.ReplyInThread) add(TimelineItemAction.Reply) } else { - if (!isThreadsEnabled && timelineItem.threadInfo.threadRootId != null) { + if (!isThreadsEnabled && timelineItem.threadInfo is TimelineItemThreadInfo.ThreadResponse) { // If threads are not enabled, we can reply in a thread if the item is already in the thread add(TimelineItemAction.ReplyInThread) } else { 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 3c03f4a7b0..e7dc71f185 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 @@ -16,6 +16,7 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions import io.element.android.features.messages.impl.timeline.model.TimelineItemReadReceipts +import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo import io.element.android.features.messages.impl.timeline.model.anAggregatedReaction import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent @@ -32,7 +33,6 @@ import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom import io.element.android.libraries.matrix.api.timeline.Timeline -import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo 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 @@ -146,7 +146,7 @@ internal fun aTimelineItemEvent( groupPosition: TimelineItemGroupPosition = TimelineItemGroupPosition.None, sendState: LocalEventSendState? = null, inReplyTo: InReplyToDetails? = null, - threadInfo: EventThreadInfo = EventThreadInfo(threadRootId = null, threadSummary = null), + threadInfo: TimelineItemThreadInfo? = null, debugInfo: TimelineItemDebugInfo = aTimelineItemDebugInfo(), timelineItemReactions: TimelineItemReactions = aTimelineItemReactions(), readReceiptState: TimelineItemReadReceipts = aTimelineItemReadReceipts(), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt index 04fe0cb481..1dbe5d3a24 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt @@ -53,8 +53,6 @@ import io.element.android.libraries.ui.utils.time.isTalkbackActive private val BUBBLE_RADIUS = 12.dp private val avatarRadius = AvatarSize.TimelineSender.dp / 2 -// Design says: The maximum width of a bubble is still 3/4 of the screen width. But try with 78% now. -private const val BUBBLE_WIDTH_RATIO = 0.78f private val MIN_BUBBLE_WIDTH = 80.dp @Composable @@ -66,34 +64,6 @@ fun MessageEventBubble( modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit = {}, ) { - fun bubbleShape(): Shape { - val topLeftCorner = if (state.cutTopStart) 0.dp else BUBBLE_RADIUS - return when (state.groupPosition) { - TimelineItemGroupPosition.First -> if (state.isMine) { - RoundedCornerShape(BUBBLE_RADIUS, BUBBLE_RADIUS, 0.dp, BUBBLE_RADIUS) - } else { - RoundedCornerShape(topLeftCorner, BUBBLE_RADIUS, BUBBLE_RADIUS, 0.dp) - } - TimelineItemGroupPosition.Middle -> if (state.isMine) { - RoundedCornerShape(BUBBLE_RADIUS, 0.dp, 0.dp, BUBBLE_RADIUS) - } else { - RoundedCornerShape(0.dp, BUBBLE_RADIUS, BUBBLE_RADIUS, 0.dp) - } - TimelineItemGroupPosition.Last -> if (state.isMine) { - RoundedCornerShape(BUBBLE_RADIUS, 0.dp, BUBBLE_RADIUS, BUBBLE_RADIUS) - } else { - RoundedCornerShape(0.dp, BUBBLE_RADIUS, BUBBLE_RADIUS, BUBBLE_RADIUS) - } - TimelineItemGroupPosition.None -> - RoundedCornerShape( - topLeftCorner, - BUBBLE_RADIUS, - BUBBLE_RADIUS, - BUBBLE_RADIUS - ) - } - } - val clickableModifier = if (isTalkbackActive()) { Modifier } else { @@ -108,11 +78,8 @@ fun MessageEventBubble( } // Ignore state.isHighlighted for now, we need a design decision on it. - val backgroundBubbleColor = when { - state.isMine -> ElementTheme.colors.messageFromMeBackground - else -> ElementTheme.colors.messageFromOtherBackground - } - val bubbleShape = bubbleShape() + val backgroundBubbleColor = MessageEventBubbleDefaults.backgroundBubbleColor(state.isMine) + val bubbleShape = remember(state) { MessageEventBubbleDefaults.shape(state.cutTopStart, state.groupPosition, state.isMine) } val radiusPx = (avatarRadius + SENDER_AVATAR_BORDER_WIDTH).toPx() val yOffsetPx = -(NEGATIVE_MARGIN_FOR_BUBBLE + avatarRadius).toPx() val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl @@ -147,7 +114,7 @@ fun MessageEventBubble( .testTag(TestTags.messageBubble) .widthIn( min = MIN_BUBBLE_WIDTH, - max = (constraints.maxWidth * BUBBLE_WIDTH_RATIO) + max = (constraints.maxWidth * MessageEventBubbleDefaults.BUBBLE_WIDTH_RATIO) .toInt() .toDp() ) @@ -157,6 +124,48 @@ fun MessageEventBubble( } } +object MessageEventBubbleDefaults { + fun shape(cutTopStart: Boolean, groupPosition: TimelineItemGroupPosition, isMine: Boolean): Shape { + val topLeftCorner = if (cutTopStart) 0.dp else BUBBLE_RADIUS + return when (groupPosition) { + TimelineItemGroupPosition.First -> if (isMine) { + RoundedCornerShape(BUBBLE_RADIUS, BUBBLE_RADIUS, 0.dp, BUBBLE_RADIUS) + } else { + RoundedCornerShape(topLeftCorner, BUBBLE_RADIUS, BUBBLE_RADIUS, 0.dp) + } + TimelineItemGroupPosition.Middle -> if (isMine) { + RoundedCornerShape(BUBBLE_RADIUS, 0.dp, 0.dp, BUBBLE_RADIUS) + } else { + RoundedCornerShape(0.dp, BUBBLE_RADIUS, BUBBLE_RADIUS, 0.dp) + } + TimelineItemGroupPosition.Last -> if (isMine) { + RoundedCornerShape(BUBBLE_RADIUS, 0.dp, BUBBLE_RADIUS, BUBBLE_RADIUS) + } else { + RoundedCornerShape(0.dp, BUBBLE_RADIUS, BUBBLE_RADIUS, BUBBLE_RADIUS) + } + TimelineItemGroupPosition.None -> + RoundedCornerShape( + topLeftCorner, + BUBBLE_RADIUS, + BUBBLE_RADIUS, + BUBBLE_RADIUS + ) + } + } + + @Composable + fun backgroundBubbleColor(isMine: Boolean): Color { + return if (isMine) { + ElementTheme.colors.messageFromMeBackground + } else { + ElementTheme.colors.messageFromOtherBackground + } + } + + // Design says: The maximum width of a bubble is still 3/4 of the screen width. But try with 78% now. + const val BUBBLE_WIDTH_RATIO = 0.78f +} + @PreviewsDayNight @Composable internal fun MessageEventBubblePreview(@PreviewParameter(BubbleStateProvider::class) state: BubbleState) = ElementPreview { 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 de4cfe2c2a..fb45278b78 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 @@ -15,6 +15,7 @@ import androidx.compose.foundation.gestures.draggable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -23,6 +24,8 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -34,6 +37,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalViewConfiguration import androidx.compose.ui.platform.ViewConfiguration import androidx.compose.ui.res.pluralStringResource @@ -43,6 +47,7 @@ import androidx.compose.ui.semantics.hideFromAccessibility import androidx.compose.ui.semantics.isTraversalGroup import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.traversalIndex +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp @@ -61,6 +66,7 @@ import io.element.android.features.messages.impl.timeline.components.receipt.Rea import io.element.android.features.messages.impl.timeline.components.receipt.TimelineItemReadReceiptView import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition +import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo import io.element.android.features.messages.impl.timeline.model.bubble.BubbleState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent @@ -78,25 +84,28 @@ 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 import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType +import io.element.android.libraries.designsystem.modifiers.niceClickable import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.swipe.SwipeableActionsState import io.element.android.libraries.designsystem.swipe.rememberSwipeableActionsState import io.element.android.libraries.designsystem.text.toPx -import io.element.android.libraries.designsystem.theme.components.Button -import io.element.android.libraries.designsystem.theme.components.ButtonSize 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.core.EventId -import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.toThreadId import io.element.android.libraries.matrix.api.timeline.Timeline -import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo +import io.element.android.libraries.matrix.api.timeline.item.EmbeddedEventInfo import io.element.android.libraries.matrix.api.timeline.item.ThreadSummary +import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId +import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType import io.element.android.libraries.matrix.api.timeline.item.event.getAvatarUrl +import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName import io.element.android.libraries.matrix.api.timeline.item.event.getDisplayName import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails @@ -256,22 +265,22 @@ fun TimelineItemEventRow( ) } - if (displayThreadSummaries && timelineMode !is Timeline.Mode.Thread) { - event.threadInfo.threadSummary?.let { threadSummary -> - val threadPart = stringResource(CommonStrings.common_thread) - val numberOfReplies = threadSummary.numberOfReplies.toInt().let { replies -> - pluralStringResource(CommonPlurals.common_replies, replies, replies) + if (displayThreadSummaries && timelineMode !is Timeline.Mode.Thread && event.threadInfo is TimelineItemThreadInfo.ThreadRoot) { + ThreadSummaryView( + modifier = if (event.isMine) { + Modifier.align(Alignment.End).padding(end = 16.dp) + } else { + if (timelineRoomInfo.isDm) Modifier else Modifier.padding(start = 16.dp) + }.padding(top = 2.dp), + threadSummary = event.threadInfo.summary, + latestEventText = event.threadInfo.latestEventText, + isOutgoing = event.isMine, + onClick = { + event.eventId?.let { + eventSink(TimelineEvents.OpenThread(it.toThreadId(), null)) + } } - Button( - modifier = Modifier.padding(horizontal = 24.dp, vertical = 2.dp) - .align(if (event.isMine) Alignment.End else Alignment.Start), - text = "$threadPart - $numberOfReplies", - size = ButtonSize.Small, - onClick = { - eventSink(TimelineEvents.OpenThread(event.eventId!!.toThreadId(), null)) - }, - ) - } + ) } // Read receipts / Send state @@ -288,6 +297,79 @@ fun TimelineItemEventRow( } } +@Composable +private fun ThreadSummaryView( + threadSummary: ThreadSummary, + latestEventText: String?, + isOutgoing: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + BoxWithConstraints(modifier = modifier) { + Row( + modifier = Modifier + .then(if (!isOutgoing) Modifier.padding(start = 16.dp) else Modifier) + .graphicsLayer { + shape = RoundedCornerShape(8.dp) + clip = true + } + .background(MessageEventBubbleDefaults.backgroundBubbleColor(isOutgoing)) + .niceClickable(onClick) + .padding(horizontal = 12.dp, vertical = 10.dp) + .widthIn(max = (maxWidth - 24.dp) * MessageEventBubbleDefaults.BUBBLE_WIDTH_RATIO), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = CompoundIcons.ThreadsSolid(), + contentDescription = null, + tint = ElementTheme.colors.iconSecondary, + ) + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = pluralStringResource(CommonPlurals.common_replies, threadSummary.numberOfReplies.toInt(), threadSummary.numberOfReplies), + style = ElementTheme.typography.fontBodySmMedium, + color = ElementTheme.colors.textSecondary, + ) + + Spacer(modifier = Modifier.width(8.dp)) + + threadSummary.latestEvent.dataOrNull()?.let { latestEvent -> + val avatarData = AvatarData( + id = latestEvent.senderId.value, + name = latestEvent.senderProfile.getDisplayName(), + url = latestEvent.senderProfile.getAvatarUrl(), + size = AvatarSize.TimelineThreadLatestEventSender, + ) + Avatar( + avatarData = avatarData, + avatarType = AvatarType.User, + ) + + Spacer(modifier = Modifier.width(8.dp)) + + Text( + text = latestEvent.senderProfile.getDisambiguatedDisplayName(latestEvent.senderId), + style = ElementTheme.typography.fontBodySmMedium, + color = ElementTheme.colors.textSecondary, + ) + + Spacer(modifier = Modifier.width(4.dp)) + + latestEventText?.let { + Text( + text = it, + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textSecondary, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + ) + } + } + } + } +} + /** * Impact ViewConfiguration.touchSlop by [sensitivityFactor]. * Inspired from https://issuetracker.google.com/u/1/issues/269627294. @@ -694,7 +776,7 @@ private fun MessageEventBubbleContent( else -> ContentPadding.Textual } CommonLayout( - showThreadDecoration = timelineMode !is Timeline.Mode.Thread && event.threadInfo.threadRootId != null, + showThreadDecoration = timelineMode !is Timeline.Mode.Thread && event.threadInfo is TimelineItemThreadInfo.ThreadResponse, timestampPosition = timestampPosition, paddingBehaviour = paddingBehaviour, inReplyToDetails = event.inReplyTo, @@ -746,9 +828,27 @@ internal fun TimelineItemEventRowWithThreadSummaryPreview() = ElementPreview { " hopefully can be manually adjusted to test different behaviors." ), groupPosition = TimelineItemGroupPosition.First, - threadInfo = EventThreadInfo( - threadRootId = ThreadId("\$thread-root-id"), - threadSummary = ThreadSummary(AsyncData.Uninitialized, numberOfReplies = 20L) + threadInfo = TimelineItemThreadInfo.ThreadRoot( + latestEventText = "This is the latest message in the thread", + summary = ThreadSummary(AsyncData.Success( + EmbeddedEventInfo( + eventOrTransactionId = EventOrTransactionId.Event(EventId("\$event-id")), + content = MessageContent( + body = "This is the latest message in the thread", + inReplyTo = null, + isEdited = false, + threadInfo = null, + type = TextMessageType("This is the latest message in the thread", null) + ), + senderId = UserId("@user:id"), + senderProfile = ProfileTimelineDetails.Ready( + displayName = "Alice", + avatarUrl = null, + displayNameAmbiguous = false, + ), + timestamp = 0L, + ) + ), numberOfReplies = 20L) ) ), displayThreadSummaries = true, @@ -756,3 +856,40 @@ internal fun TimelineItemEventRowWithThreadSummaryPreview() = ElementPreview { } } } + +@PreviewsDayNight +@Composable +internal fun ThreadSummaryViewPreview() { + ElementPreview { + val body = "This is the latest message in the thread" + val threadSummary = ThreadSummary( + AsyncData.Success( + EmbeddedEventInfo( + eventOrTransactionId = EventOrTransactionId.Event(EventId("\$event-id")), + content = MessageContent( + body = body, + inReplyTo = null, + isEdited = false, + threadInfo = null, + type = TextMessageType(body, null) + ), + senderId = UserId("@user:id"), + senderProfile = ProfileTimelineDetails.Ready( + displayName = "Alice", + avatarUrl = null, + displayNameAmbiguous = true, + ), + timestamp = 0L, + ) + ), + numberOfReplies = 12, + ) + + ThreadSummaryView( + threadSummary = threadSummary, + latestEventText = "Some event with a very long text that should get clipped", + isOutgoing = true, + onClick = {}, + ) + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowWithReplyPreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowWithReplyPreview.kt index 61e86a8d59..7cc1843466 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowWithReplyPreview.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowWithReplyPreview.kt @@ -13,12 +13,12 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReactions import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition +import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo 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.core.ThreadId -import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetailsProvider @@ -58,10 +58,7 @@ internal fun TimelineItemEventRowWithReplyContentToPreview( ), inReplyTo = inReplyToDetails, displayNameAmbiguous = displayNameAmbiguous, - threadInfo = EventThreadInfo( - threadRootId = ThreadId("\$thread-root-id"), - threadSummary = null, - ), + threadInfo = TimelineItemThreadInfo.ThreadResponse(threadRootId = ThreadId("\$thread-root-id")), groupPosition = TimelineItemGroupPosition.Last, ), ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt index 643d0f55ad..8047acd09a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt @@ -12,7 +12,10 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent +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.CallNotifyContent +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 @@ -20,6 +23,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.LegacyCallInv import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent import io.element.android.libraries.matrix.api.timeline.item.event.PollContent import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails 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 @@ -27,6 +31,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.StickerConten 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.getDisambiguatedDisplayName +import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder @Inject class TimelineItemContentFactory( @@ -40,26 +45,53 @@ class TimelineItemContentFactory( private val stateFactory: TimelineItemContentStateFactory, private val failedToParseMessageFactory: TimelineItemContentFailedToParseMessageFactory, private val failedToParseStateFactory: TimelineItemContentFailedToParseStateFactory, + private val currentSessionIdHolder: CurrentSessionIdHolder, ) { suspend fun create(eventTimelineItem: EventTimelineItem): TimelineItemEventContent { - return when (val itemContent = eventTimelineItem.content) { + return create( + itemContent = eventTimelineItem.content, + eventId = eventTimelineItem.eventId, + isEditable = eventTimelineItem.isEditable, + sender = eventTimelineItem.sender, + senderProfile = eventTimelineItem.senderProfile, + ) + } + + suspend fun create( + itemContent: EventContent, + eventId: EventId?, + isEditable: Boolean, + sender: UserId, + senderProfile: ProfileTimelineDetails, + ): TimelineItemEventContent { + val isOutgoing = currentSessionIdHolder.current == sender + return when (itemContent) { is FailedToParseMessageLikeContent -> failedToParseMessageFactory.create(itemContent) is FailedToParseStateContent -> failedToParseStateFactory.create(itemContent) is MessageContent -> { - val senderDisambiguatedDisplayName = eventTimelineItem.senderProfile.getDisambiguatedDisplayName(eventTimelineItem.sender) + val senderDisambiguatedDisplayName = senderProfile.getDisambiguatedDisplayName(sender) messageFactory.create( content = itemContent, senderDisambiguatedDisplayName = senderDisambiguatedDisplayName, - eventId = eventTimelineItem.eventId, + eventId = eventId, ) } - is ProfileChangeContent -> profileChangeFactory.create(eventTimelineItem) + is ProfileChangeContent -> { + val senderDisambiguatedDisplayName = senderProfile.getDisambiguatedDisplayName(sender) + profileChangeFactory.create(itemContent, isOutgoing, sender, senderDisambiguatedDisplayName) + } is RedactedContent -> redactedMessageFactory.create(itemContent) - is RoomMembershipContent -> roomMembershipFactory.create(eventTimelineItem) + is RoomMembershipContent -> { + val senderDisambiguatedDisplayName = senderProfile.getDisambiguatedDisplayName(sender) + roomMembershipFactory.create(itemContent, isOutgoing, sender, senderDisambiguatedDisplayName) + } is LegacyCallInviteContent -> TimelineItemLegacyCallInviteContent - is StateContent -> stateFactory.create(eventTimelineItem) + is StateContent -> { + val senderDisambiguatedDisplayName = senderProfile.getDisambiguatedDisplayName(sender) + stateFactory.create(itemContent, isOutgoing, sender, senderDisambiguatedDisplayName) + } is StickerContent -> stickerFactory.create(itemContent) - is PollContent -> pollFactory.create(eventTimelineItem, itemContent) + is PollContent -> pollFactory.create(eventId, isEditable, isOutgoing, itemContent) is UnableToDecryptContent -> utdFactory.create(itemContent) is CallNotifyContent -> TimelineItemRtcNotificationContent() is UnknownContent -> TimelineItemUnknownContent diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt index bb2f7fe138..ec2eba6544 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt @@ -11,7 +11,7 @@ import dev.zacsweers.metro.Inject import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent import io.element.android.features.poll.api.pollcontent.PollContentStateFactory -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.item.event.PollContent @Inject @@ -19,14 +19,16 @@ class TimelineItemContentPollFactory( private val pollContentStateFactory: PollContentStateFactory, ) { suspend fun create( - event: EventTimelineItem, + eventId: EventId?, + isEditable: Boolean, + isOwn: Boolean, content: PollContent, ): TimelineItemEventContent { - val pollContentState = pollContentStateFactory.create(event, content) + val pollContentState = pollContentStateFactory.create(eventId, isEditable, isOwn, content) return TimelineItemPollContent( isMine = pollContentState.isMine, isEditable = pollContentState.isPollEditable, - eventId = event.eventId, + eventId = eventId, question = pollContentState.question, answerItems = pollContentState.answerItems, pollKind = pollContentState.pollKind, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentProfileChangeFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentProfileChangeFactory.kt index b01a19bf41..a0a0b1f357 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentProfileChangeFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentProfileChangeFactory.kt @@ -12,14 +12,15 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemProfileChangeContent import io.element.android.libraries.core.extensions.orEmpty import io.element.android.libraries.eventformatter.api.TimelineEventFormatter -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.timeline.item.event.EventContent @Inject class TimelineItemContentProfileChangeFactory( private val timelineEventFormatter: TimelineEventFormatter, ) { - fun create(eventTimelineItem: EventTimelineItem): TimelineItemEventContent { - val text = timelineEventFormatter.format(eventTimelineItem) + fun create(content: EventContent, isOutgoing: Boolean, sender: UserId, senderDisambiguatedDisplayName: String): TimelineItemEventContent { + val text = timelineEventFormatter.format(content, isOutgoing, sender, senderDisambiguatedDisplayName) return TimelineItemProfileChangeContent(text.orEmpty().toString()) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentRoomMembershipFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentRoomMembershipFactory.kt index 3fbd7357e6..a602e5274b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentRoomMembershipFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentRoomMembershipFactory.kt @@ -12,14 +12,15 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRoomMembershipContent import io.element.android.libraries.core.extensions.orEmpty import io.element.android.libraries.eventformatter.api.TimelineEventFormatter -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.timeline.item.event.EventContent @Inject class TimelineItemContentRoomMembershipFactory( private val timelineEventFormatter: TimelineEventFormatter, ) { - fun create(eventTimelineItem: EventTimelineItem): TimelineItemEventContent { - val text = timelineEventFormatter.format(eventTimelineItem) + fun create(eventContent: EventContent, isOutgoing: Boolean, sender: UserId, senderDisambiguatedDisplayName: String): TimelineItemEventContent { + val text = timelineEventFormatter.format(eventContent, isOutgoing, sender, senderDisambiguatedDisplayName) return TimelineItemRoomMembershipContent(text.orEmpty().toString()) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentStateFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentStateFactory.kt index 38d41f9341..6716a7ff83 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentStateFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentStateFactory.kt @@ -12,14 +12,15 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateEventContent import io.element.android.libraries.core.extensions.orEmpty import io.element.android.libraries.eventformatter.api.TimelineEventFormatter -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.timeline.item.event.EventContent @Inject class TimelineItemContentStateFactory( private val timelineEventFormatter: TimelineEventFormatter, ) { - fun create(eventTimelineItem: EventTimelineItem): TimelineItemEventContent { - val text = timelineEventFormatter.format(eventTimelineItem) + fun create(eventContent: EventContent, isOutgoing: Boolean, sender: UserId, senderDisambiguatedDisplayName: String): TimelineItemEventContent { + val text = timelineEventFormatter.format(eventContent, isOutgoing, sender, senderDisambiguatedDisplayName) return TimelineItemStateEventContent(text.orEmpty().toString()) } } 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 814f966f8b..d3b3c5d679 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 @@ -19,6 +19,9 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions import io.element.android.features.messages.impl.timeline.model.TimelineItemReadReceipts +import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo +import io.element.android.features.messages.impl.utils.messagesummary.MessageSummaryFormatter +import io.element.android.libraries.architecture.map import io.element.android.libraries.core.bool.orTrue import io.element.android.libraries.dateformatter.api.DateFormatter import io.element.android.libraries.dateformatter.api.DateFormatterMode @@ -43,6 +46,7 @@ class TimelineItemEventFactory( private val matrixClient: MatrixClient, private val dateFormatter: DateFormatter, private val permalinkParser: PermalinkParser, + private val summaryFormatter: MessageSummaryFormatter, ) { @AssistedFactory interface Creator { @@ -69,6 +73,29 @@ class TimelineItemEventFactory( url = senderProfile.getAvatarUrl(), size = AvatarSize.TimelineSender ) + val mappedThreadInfo = when (val threadInfo = currentTimelineItem.event.threadInfo()) { + is EventThreadInfo.ThreadResponse -> { + TimelineItemThreadInfo.ThreadResponse(threadInfo.threadRootId) + } + is EventThreadInfo.ThreadRoot -> { + TimelineItemThreadInfo.ThreadRoot( + summary = threadInfo.summary, + latestEventText = threadInfo.summary.latestEvent.dataOrNull() + ?.let { + contentFactory.create( + itemContent = it.content, + eventId = it.eventOrTransactionId.eventId, + isEditable = false, + sender = it.senderId, + senderProfile = it.senderProfile, + ) + } + ?.let(summaryFormatter::format) + ) + } + null -> null + } + return TimelineItem.Event( id = currentTimelineItem.uniqueId, eventId = currentTimelineItem.eventId, @@ -87,7 +114,7 @@ class TimelineItemEventFactory( readReceiptState = currentTimelineItem.computeReadReceiptState(roomMembers), localSendState = currentTimelineItem.event.localSendState, inReplyTo = currentTimelineItem.event.inReplyTo()?.map(permalinkParser = permalinkParser), - threadInfo = currentTimelineItem.event.threadInfo() ?: EventThreadInfo(threadRootId = null, threadSummary = null), + threadInfo = mappedThreadInfo, origin = currentTimelineItem.event.origin, timelineItemDebugInfoProvider = currentTimelineItem.event.timelineItemDebugInfoProvider, messageShieldProvider = currentTimelineItem.event.messageShieldProvider, 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 94e04dd1d8..5591616517 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 @@ -17,10 +17,11 @@ import io.element.android.features.messages.impl.timeline.model.virtual.Timeline import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.SendHandle +import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo +import io.element.android.libraries.matrix.api.timeline.item.ThreadSummary import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState @@ -82,7 +83,7 @@ sealed interface TimelineItem { val readReceiptState: TimelineItemReadReceipts, val localSendState: LocalEventSendState?, val inReplyTo: InReplyToDetails?, - val threadInfo: EventThreadInfo, + val threadInfo: TimelineItemThreadInfo?, val origin: TimelineItemEventOrigin?, val timelineItemDebugInfoProvider: TimelineItemDebugInfoProvider, val messageShieldProvider: MessageShieldProvider, @@ -130,3 +131,8 @@ sealed interface TimelineItem { val aggregatedReadReceipts: ImmutableList, ) : TimelineItem } + +sealed interface TimelineItemThreadInfo { + data class ThreadRoot(val summary: ThreadSummary, val latestEventText: String?) : TimelineItemThreadInfo + data class ThreadResponse(val threadRootId: ThreadId) : TimelineItemThreadInfo +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt index 22c67ed2f2..1f1619e3f6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt @@ -10,9 +10,9 @@ package io.element.android.features.messages.impl.utils.messagesummary import android.content.Context import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Inject -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.TimelineItemEncryptedContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent @@ -37,15 +37,15 @@ import io.element.android.libraries.ui.strings.CommonStrings class DefaultMessageSummaryFormatter( @ApplicationContext private val context: Context, ) : MessageSummaryFormatter { - override fun format(event: TimelineItem.Event): String { - return when (event.content) { - is TimelineItemTextBasedContent -> event.content.plainText - is TimelineItemProfileChangeContent -> event.content.body - is TimelineItemStateContent -> event.content.body + override fun format(content: TimelineItemEventContent): String { + return when (content) { + is TimelineItemTextBasedContent -> content.plainText + is TimelineItemProfileChangeContent -> content.body + is TimelineItemStateContent -> content.body is TimelineItemLocationContent -> context.getString(CommonStrings.common_shared_location) is TimelineItemEncryptedContent -> context.getString(CommonStrings.common_unable_to_decrypt) is TimelineItemRedactedContent -> context.getString(CommonStrings.common_message_removed) - is TimelineItemPollContent -> event.content.question + is TimelineItemPollContent -> content.question is TimelineItemVoiceContent -> context.getString(CommonStrings.common_voice_message) is TimelineItemUnknownContent -> context.getString(CommonStrings.common_unsupported_event) is TimelineItemImageContent -> context.getString(CommonStrings.common_image) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/MessageSummaryFormatter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/MessageSummaryFormatter.kt index 393ed21fa5..6e590c8779 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/MessageSummaryFormatter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/MessageSummaryFormatter.kt @@ -8,7 +8,11 @@ package io.element.android.features.messages.impl.utils.messagesummary import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent interface MessageSummaryFormatter { - fun format(event: TimelineItem.Event): String + fun format(event: TimelineItem.Event): String { + return format(event.content) + } + fun format(content: TimelineItemEventContent): String } 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 122dd021a4..52c5ee2259 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 @@ -26,6 +26,7 @@ import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMess 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.aTimelineState +import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent @@ -61,7 +62,6 @@ import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom import io.element.android.libraries.matrix.api.timeline.Timeline -import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId @@ -1181,7 +1181,7 @@ class MessagesPresenterTest { val initialState = awaitItem() initialState.eventSink(MessagesEvents.HandleAction( action = TimelineItemAction.ReplyInThread, - event = aMessageEvent(threadInfo = EventThreadInfo(A_THREAD_ID, null)) + event = aMessageEvent(threadInfo = TimelineItemThreadInfo.ThreadResponse(A_THREAD_ID)) )) awaitItem() openThreadLambda.assertions().isCalledOnce().with(value(A_THREAD_ID), value(null)) @@ -1204,7 +1204,7 @@ class MessagesPresenterTest { event = aMessageEvent( // The event id will be used as the thread id instead eventId = AN_EVENT_ID, - threadInfo = EventThreadInfo(null, null), + threadInfo = null, ) )) awaitItem() 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 d6188e0e76..e8766798cd 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 @@ -18,6 +18,7 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.timeline.aTimelineItemEvent +import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent @@ -31,7 +32,6 @@ import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.timeline.Timeline -import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_CAPTION @@ -198,7 +198,7 @@ class ActionListPresenterTest { val messageEvent = aMessageEvent( isMine = false, isEditable = false, - threadInfo = EventThreadInfo(threadRootId = A_THREAD_ID, threadSummary = null), + threadInfo = TimelineItemThreadInfo.ThreadResponse(threadRootId = A_THREAD_ID), content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( @@ -432,7 +432,7 @@ class ActionListPresenterTest { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, - threadInfo = EventThreadInfo(threadRootId = A_THREAD_ID, threadSummary = null), + threadInfo = TimelineItemThreadInfo.ThreadResponse(threadRootId = A_THREAD_ID), content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( @@ -1264,7 +1264,7 @@ class ActionListPresenterTest { content = aTimelineItemVoiceContent( caption = null, ), - threadInfo = EventThreadInfo(A_THREAD_ID, null) + threadInfo = TimelineItemThreadInfo.ThreadResponse(threadRootId = A_THREAD_ID) ) initialState.eventSink.invoke( ActionListEvents.ComputeForMessage( @@ -1368,7 +1368,7 @@ class ActionListPresenterTest { content = aTimelineItemVoiceContent( caption = null, ), - threadInfo = EventThreadInfo(A_THREAD_ID, null), + threadInfo = TimelineItemThreadInfo.ThreadResponse(threadRootId = A_THREAD_ID), ) assertThat(messageEvent.isRemote).isTrue() 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 a9f2e075ac..703b4b0043 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 @@ -12,6 +12,7 @@ import io.element.android.features.messages.impl.timeline.aTimelineItemReactions import io.element.android.features.messages.impl.timeline.model.ReadReceiptData import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItemReadReceipts +import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -19,7 +20,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize 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.core.UniqueId -import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.timeline.item.event.MessageShieldProvider import io.element.android.libraries.matrix.api.timeline.item.event.SendHandleProvider @@ -41,7 +41,7 @@ internal fun aMessageEvent( canBeRepliedTo: Boolean = true, content: TimelineItemEventContent = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, formattedBody = A_MESSAGE, isEdited = false), inReplyTo: InReplyToDetails? = null, - threadInfo: EventThreadInfo = EventThreadInfo(threadRootId = null, threadSummary = null), + threadInfo: TimelineItemThreadInfo? = null, sendState: LocalEventSendState = LocalEventSendState.Sent(AN_EVENT_ID), debugInfoProvider: TimelineItemDebugInfoProvider = TimelineItemDebugInfoProvider { aTimelineItemDebugInfo() }, messageShieldProvider: MessageShieldProvider = MessageShieldProvider { null }, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt index 2cf0f8a3c9..502ab74062 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt @@ -7,6 +7,7 @@ package io.element.android.features.messages.impl.fixtures +import io.element.android.features.messages.impl.messagesummary.FakeMessageSummaryFormatter import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactoryConfig import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemContentFactory @@ -30,7 +31,9 @@ import io.element.android.features.poll.test.pollcontent.FakePollContentStateFac import io.element.android.libraries.androidutils.filesize.FakeFileSizeFormatter import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.eventformatter.api.TimelineEventFormatter -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.timeline.item.event.EventContent +import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser import io.element.android.libraries.mediaviewer.test.util.FileExtensionExtractorWithoutValidation @@ -75,11 +78,13 @@ internal fun TestScope.aTimelineItemsFactory( stateFactory = TimelineItemContentStateFactory(timelineEventFormatter), failedToParseMessageFactory = TimelineItemContentFailedToParseMessageFactory(), failedToParseStateFactory = TimelineItemContentFailedToParseStateFactory(), + currentSessionIdHolder = CurrentSessionIdHolder(matrixClient), ), matrixClient = matrixClient, dateFormatter = FakeDateFormatter(), permalinkParser = FakePermalinkParser(), - config = config + config = config, + summaryFormatter = FakeMessageSummaryFormatter(), ) } }, @@ -95,7 +100,7 @@ internal fun TestScope.aTimelineItemsFactory( internal fun aTimelineEventFormatter(): TimelineEventFormatter { return object : TimelineEventFormatter { - override fun format(event: EventTimelineItem): CharSequence { + override fun format(content: EventContent, isOutgoing: Boolean, sender: UserId, senderDisambiguatedDisplayName: String): CharSequence? { return "" } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagesummary/FakeMessageSummaryFormatter.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagesummary/FakeMessageSummaryFormatter.kt index 315f2e3a7a..06d1cca1c7 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagesummary/FakeMessageSummaryFormatter.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagesummary/FakeMessageSummaryFormatter.kt @@ -7,13 +7,13 @@ package io.element.android.features.messages.impl.messagesummary -import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.utils.messagesummary.MessageSummaryFormatter class FakeMessageSummaryFormatter : MessageSummaryFormatter { private var result = "A message" - override fun format(event: TimelineItem.Event): String = result + override fun format(content: TimelineItemEventContent): String = result fun givenMessageResult(value: String) { result = value diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt index 917683220e..fb13103694 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt @@ -750,7 +750,7 @@ class TimelineItemContentMessageFactoryTest { body: String = "Body", inReplyTo: InReplyTo? = null, isEdited: Boolean = false, - threadInfo: EventThreadInfo = EventThreadInfo(threadRootId = null, threadSummary = null), + threadInfo: EventThreadInfo? = null, type: MessageType, ): MessageContent { return MessageContent( 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 188c5f0bcd..1bdc43ebef 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 @@ -18,7 +18,6 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.virtual.aTimelineItemDaySeparatorModel import io.element.android.libraries.designsystem.components.avatar.anAvatarData import io.element.android.libraries.matrix.api.core.UniqueId -import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_USER_ID @@ -42,7 +41,7 @@ class TimelineItemGrouperTest { isEditable = false, canBeRepliedTo = false, inReplyTo = null, - threadInfo = EventThreadInfo(threadRootId = null, threadSummary = null), + threadInfo = null, origin = null, timelineItemDebugInfoProvider = { aTimelineItemDebugInfo() }, messageShieldProvider = { null }, diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/pollcontent/PollContentStateFactory.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/pollcontent/PollContentStateFactory.kt index 5229534cc4..e42bb98bef 100644 --- a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/pollcontent/PollContentStateFactory.kt +++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/pollcontent/PollContentStateFactory.kt @@ -7,9 +7,18 @@ package io.element.android.features.poll.api.pollcontent +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.PollContent interface PollContentStateFactory { - suspend fun create(event: EventTimelineItem, content: PollContent): PollContentState + suspend fun create(eventTimelineItem: EventTimelineItem, content: PollContent): PollContentState { + return create( + eventId = eventTimelineItem.eventId, + isEditable = eventTimelineItem.isEditable, + isOwn = eventTimelineItem.isOwn, + content = content, + ) + } + suspend fun create(eventId: EventId?, isEditable: Boolean, isOwn: Boolean, content: PollContent): PollContentState } diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/model/PollHistoryItemsFactory.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/model/PollHistoryItemsFactory.kt index 3db799bce9..2a9c802e6b 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/model/PollHistoryItemsFactory.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/model/PollHistoryItemsFactory.kt @@ -45,7 +45,12 @@ class PollHistoryItemsFactory( return when (timelineItem) { is MatrixTimelineItem.Event -> { val pollContent = timelineItem.event.content as? PollContent ?: return null - val pollContentState = pollContentStateFactory.create(timelineItem.event, pollContent) + val pollContentState = pollContentStateFactory.create( + eventId = timelineItem.eventId, + isEditable = timelineItem.event.isEditable, + isOwn = timelineItem.event.isOwn, + content = pollContent, + ) PollHistoryItem( formattedDate = dateFormatter.format( timestamp = timelineItem.event.timestamp, diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/model/DefaultPollContentStateFactory.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/model/DefaultPollContentStateFactory.kt index d506b72cf5..8647d80f23 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/model/DefaultPollContentStateFactory.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/model/DefaultPollContentStateFactory.kt @@ -14,8 +14,8 @@ import io.element.android.features.poll.api.pollcontent.PollContentState import io.element.android.features.poll.api.pollcontent.PollContentStateFactory import io.element.android.libraries.di.RoomScope import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.poll.isDisclosed -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.PollContent import kotlinx.collections.immutable.toImmutableList @@ -25,8 +25,10 @@ class DefaultPollContentStateFactory( private val matrixClient: MatrixClient, ) : PollContentStateFactory { override suspend fun create( - event: EventTimelineItem, - content: PollContent + eventId: EventId?, + isEditable: Boolean, + isOwn: Boolean, + content: PollContent, ): PollContentState { val totalVoteCount = content.votes.flatMap { it.value }.size val myVotes = content.votes.filter { matrixClient.sessionId in it.value }.keys @@ -59,13 +61,13 @@ class DefaultPollContentStateFactory( } return PollContentState( - eventId = event.eventId, + eventId = eventId, question = content.question, answerItems = answerItems.toImmutableList(), pollKind = content.kind, - isPollEditable = event.isEditable, + isPollEditable = isEditable, isPollEnded = isPollEnded, - isMine = event.isOwn, + isMine = isOwn, ) } } diff --git a/features/poll/test/src/main/kotlin/io/element/android/features/poll/test/pollcontent/FakePollContentStateFactory.kt b/features/poll/test/src/main/kotlin/io/element/android/features/poll/test/pollcontent/FakePollContentStateFactory.kt index 4c467fddd9..701d2e4640 100644 --- a/features/poll/test/src/main/kotlin/io/element/android/features/poll/test/pollcontent/FakePollContentStateFactory.kt +++ b/features/poll/test/src/main/kotlin/io/element/android/features/poll/test/pollcontent/FakePollContentStateFactory.kt @@ -10,20 +10,20 @@ package io.element.android.features.poll.test.pollcontent import io.element.android.features.poll.api.pollcontent.PollAnswerItem import io.element.android.features.poll.api.pollcontent.PollContentState import io.element.android.features.poll.api.pollcontent.PollContentStateFactory -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.item.event.PollContent import kotlinx.collections.immutable.toImmutableList class FakePollContentStateFactory : PollContentStateFactory { - override suspend fun create(event: EventTimelineItem, content: PollContent): PollContentState { + override suspend fun create(eventId: EventId?, isEditable: Boolean, isOwn: Boolean, content: PollContent): PollContentState { return PollContentState( - eventId = event.eventId, + eventId = eventId, question = content.question, answerItems = emptyList().toImmutableList(), pollKind = content.kind, - isPollEditable = event.isEditable, + isPollEditable = isEditable, isPollEnded = content.endTime != null, - isMine = event.isOwn + isMine = isOwn, ) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt index 9e9ebb6181..f33d3a853f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt @@ -34,6 +34,7 @@ enum class AvatarSize(val dp: Dp) { TimelineRoom(32.dp), TimelineSender(32.dp), TimelineReadReceipt(16.dp), + TimelineThreadLatestEventSender(24.dp), ComposerAlert(32.dp), diff --git a/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/TimelineEventFormatter.kt b/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/TimelineEventFormatter.kt index c22ae6eb13..71920f3c4e 100644 --- a/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/TimelineEventFormatter.kt +++ b/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/TimelineEventFormatter.kt @@ -7,8 +7,19 @@ package io.element.android.libraries.eventformatter.api +import io.element.android.libraries.matrix.api.core.UserId +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.getDisambiguatedDisplayName interface TimelineEventFormatter { - fun format(event: EventTimelineItem): CharSequence? + fun format(event: EventTimelineItem): CharSequence? { + return format( + content = event.content, + isOutgoing = event.isOwn, + sender = event.sender, + senderDisambiguatedDisplayName = event.senderProfile.getDisambiguatedDisplayName(event.sender), + ) + } + fun format(content: EventContent, isOutgoing: Boolean, sender: UserId, senderDisambiguatedDisplayName: String): CharSequence? } diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultTimelineEventFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultTimelineEventFormatter.kt index ba12d03d9c..6cbe734733 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultTimelineEventFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultTimelineEventFormatter.kt @@ -13,7 +13,9 @@ import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.di.SessionScope import io.element.android.libraries.eventformatter.api.TimelineEventFormatter import io.element.android.libraries.eventformatter.impl.mode.RenderingMode +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent +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 @@ -43,12 +45,16 @@ class DefaultTimelineEventFormatter( override fun format(event: EventTimelineItem): CharSequence? { val isOutgoing = event.isOwn val senderDisambiguatedDisplayName = event.senderProfile.getDisambiguatedDisplayName(event.sender) - return when (val content = event.content) { + return format(event.content, isOutgoing, event.sender, senderDisambiguatedDisplayName) + } + + override fun format(content: EventContent, isOutgoing: Boolean, sender: UserId, senderDisambiguatedDisplayName: String): CharSequence? { + return when (content) { is RoomMembershipContent -> { roomMembershipContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing) } is ProfileChangeContent -> { - profileChangeContentFormatter.format(content, event.sender, senderDisambiguatedDisplayName, isOutgoing) + profileChangeContentFormatter.format(content, sender, senderDisambiguatedDisplayName, isOutgoing) } is StateContent -> { stateContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing, RenderingMode.Timeline) @@ -66,7 +72,7 @@ class DefaultTimelineEventFormatter( is FailedToParseStateContent, is UnknownContent -> { if (buildMeta.isDebuggable) { - error("You should not use this formatter for this event: $event") + error("You should not use this formatter for this event content: $content") } sp.getString(CommonStrings.common_unsupported_event) } diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt index 0a7d2c1e73..8fb4ac0bf4 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt @@ -14,7 +14,6 @@ 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.EventThreadInfo 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 @@ -175,7 +174,7 @@ class DefaultBaseRoomLastMessageFormatterTest { ) { val body = "Shared body" fun createMessageContent(type: MessageType): MessageContent { - return MessageContent(body, null, false, EventThreadInfo(null, null), type) + return MessageContent(body, null, false, null, type) } val sharedContentMessagesTypes = arrayOf( 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 index 349cd2585f..442357f386 100644 --- 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 @@ -14,7 +14,6 @@ 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.EventThreadInfo 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 @@ -130,7 +129,7 @@ class DefaultPinnedMessagesBannerFormatterTest { fun `Message contents`() { val body = "Shared body" fun createMessageContent(type: MessageType): MessageContent { - return MessageContent(body, null, false, EventThreadInfo(null, null), type) + return MessageContent(body, null, false, null, type) } val sharedContentMessagesTypes = arrayOf( diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/ThreadSummary.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/ThreadSummary.kt index 4960330448..c34e4c9ac3 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/ThreadSummary.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/ThreadSummary.kt @@ -14,10 +14,10 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventContent import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails -data class EventThreadInfo( - val threadRootId: ThreadId?, - val threadSummary: ThreadSummary?, -) +sealed interface EventThreadInfo { + data class ThreadRoot(val summary: ThreadSummary) : EventThreadInfo + data class ThreadResponse(val threadRootId: ThreadId) : EventThreadInfo +} data class ThreadSummary( val latestEvent: AsyncData, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt index a6bea83565..5fefe8ae31 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt @@ -24,7 +24,7 @@ data class MessageContent( val body: String, val inReplyTo: InReplyTo?, val isEdited: Boolean, - val threadInfo: EventThreadInfo, + val threadInfo: EventThreadInfo?, val type: MessageType ) : EventContent diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt index aa20ffd267..ed38c328f6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt @@ -38,7 +38,7 @@ private const val MSG_TYPE_GALLERY_UNSTABLE = "dm.filament.gallery" class EventMessageMapper { private val inReplyToMapper by lazy { InReplyToMapper(TimelineEventContentMapper()) } - fun map(message: MsgLikeKind.Message, inReplyTo: InReplyToDetails?, threadInfo: EventThreadInfo): MessageContent = message.use { + fun map(message: MsgLikeKind.Message, inReplyTo: InReplyToDetails?, threadInfo: EventThreadInfo?): MessageContent = message.use { val type = it.content.msgType.use(this::mapMessageType) val inReplyToEvent: InReplyTo? = inReplyTo?.use(inReplyToMapper::map) MessageContent( 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 4bf4592c38..0d4363f7d1 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 @@ -79,7 +79,7 @@ class TimelineEventContentMapper( content = map(latestEvent.content), senderId = UserId(latestEvent.sender), senderProfile = latestEvent.senderProfile.map(), - timestamp = latestEvent.timestamp.toLong() + timestamp = latestEvent.timestamp.toLong(), ) ) } @@ -89,10 +89,12 @@ class TimelineEventContentMapper( numberOfReplies = numberOfReplies, ) } - val threadInfo = EventThreadInfo( - threadRootId = it.content.threadRoot?.let(::ThreadId), - threadSummary = threadSummary, - ) + val threadRootId = it.content.threadRoot?.let(::ThreadId) + val threadInfo = when { + threadSummary != null -> EventThreadInfo.ThreadRoot(threadSummary) + threadRootId != null -> EventThreadInfo.ThreadResponse(threadRootId) + else -> null + } eventMessageMapper.map(kind, inReplyTo, threadInfo) } is MsgLikeKind.Redacted -> { 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 a082f6c3e1..b564c21b30 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 @@ -104,7 +104,7 @@ fun aMessageContent( body: String = "body", inReplyTo: InReplyTo? = null, isEdited: Boolean = false, - threadInfo: EventThreadInfo = EventThreadInfo(threadRootId = null, threadSummary = null), + threadInfo: EventThreadInfo? = null, messageType: MessageType = TextMessageType( body = body, formatted = null diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt index 70803c5653..f43c409f0e 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt @@ -134,10 +134,7 @@ class InReplyToDetailsOtherProvider : InReplyToDetailsProvider() { private fun aMessageContent( body: String, type: MessageType, - threadInfo: EventThreadInfo = EventThreadInfo( - threadRootId = null, - threadSummary = null, - ), + threadInfo: EventThreadInfo? = null, ) = MessageContent( body = body, inReplyTo = null, diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailTest.kt index 5b5df0e9b7..6b9683b0e0 100644 --- a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailTest.kt +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailTest.kt @@ -8,7 +8,6 @@ package io.element.android.libraries.matrix.ui.messages.reply import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo import io.element.android.libraries.matrix.api.timeline.item.event.FormattedBody import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange @@ -70,7 +69,7 @@ class InReplyToDetailTest { body = "**Hello!**", inReplyTo = null, isEdited = false, - threadInfo = EventThreadInfo(threadRootId = null, threadSummary = null), + threadInfo = null, type = TextMessageType( body = "**Hello!**", formatted = FormattedBody( @@ -95,7 +94,7 @@ class InReplyToDetailTest { body = "**Hello!**", inReplyTo = null, isEdited = false, - threadInfo = EventThreadInfo(threadRootId = null, threadSummary = null), + threadInfo = null, type = TextMessageType( body = "**Hello!**", formatted = null, diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt index bb9670de39..ab5d3bb4e1 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.textcomposer.model import androidx.compose.runtime.Immutable import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails @@ -49,7 +50,7 @@ sealed interface MessageComposerMode { get() = this is Reply && replyToDetails is InReplyToDetails.Ready && replyToDetails.eventContent is MessageContent && - (replyToDetails.eventContent as MessageContent).threadInfo.threadRootId != null + (replyToDetails.eventContent as MessageContent).threadInfo is EventThreadInfo.ThreadResponse } fun MessageComposerMode.showCaptionCompatibilityWarning(): Boolean { diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en.png new file mode 100644 index 0000000000..32733b09b6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2cb3989055cf63e3ee14d8e2d8b2cdcd67b3af1addae78b38ab13ddcf93a232d +size 9740 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en.png new file mode 100644 index 0000000000..9b9901528b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e206a2485736baa2ac8c6dae6847ef381bfa1f36a5b7bda14a7f93a55069f41 +size 9666 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en.png index 4f8761e4dd..5695ab7dc3 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddaa247eea635d7e8c079ae128983fd25c1aeba96a48b08ae71218ef52e88d5b -size 69475 +oid sha256:b51cd7375e0d9be97786632eb1dfc16b5023784ed0de616f029d782ca56aa07b +size 68221 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en.png index f17dbbe01e..a9b8b7cfc5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:647365688fd0c542d4be6dae570b33fbb7bab6261dc57791db85966808d440bb -size 67563 +oid sha256:1cb184afd2b1afff7b2f5f24f555e8278e20bbc98fe8b67a25a005771c7105b0 +size 66908 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_100_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_100_en.png index 53dbe79213..eee5b83831 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_100_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_100_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26b9908bbd388321444037dcc1aae55037d3dabc7a9f9b14c39ba871f4f9d593 -size 16128 +oid sha256:9640e8e6d758a03f995c7fbbb6c3c123109594138a7cc53d5416ef5e3e157693 +size 18006 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_101_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_101_en.png index 9c9b3d4717..70c84280d6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_101_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_101_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a96b6d95b8941d80035b309444b9eaa038098fb16aa84dec209fc3ee215ac9e -size 21687 +oid sha256:fbe699fb17947981c53d47a9570da71e2388ec493a3a9471aaa13a5405075069 +size 23421 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png index 7946dc4e91..f4e93c12ae 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce1aba18ea8a6b45d9c40de9af961952e261c7c6200ab13cdfa67906d995208b -size 14888 +oid sha256:8c6688901f89d3858ec67dda889fe589fb6b59202c64a4b700c2aa484e19f4cd +size 17606 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png index 0b12b366b9..53dbe79213 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a4d295ae71ba2709845312b84983b79348069ded46b30091b9fa769a587cbb7 -size 14337 +oid sha256:26b9908bbd388321444037dcc1aae55037d3dabc7a9f9b14c39ba871f4f9d593 +size 16128 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png index 556cb141b0..9c9b3d4717 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da8f54591a52475c6f47fa083a1bb397e1164dd3e735562388fde4ff45644150 -size 16275 +oid sha256:1a96b6d95b8941d80035b309444b9eaa038098fb16aa84dec209fc3ee215ac9e +size 21687 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png new file mode 100644 index 0000000000..7946dc4e91 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce1aba18ea8a6b45d9c40de9af961952e261c7c6200ab13cdfa67906d995208b +size 14888 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png new file mode 100644 index 0000000000..0b12b366b9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a4d295ae71ba2709845312b84983b79348069ded46b30091b9fa769a587cbb7 +size 14337 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png new file mode 100644 index 0000000000..556cb141b0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da8f54591a52475c6f47fa083a1bb397e1164dd3e735562388fde4ff45644150 +size 16275 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_45_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_45_en.png index a50251b367..38de31dfeb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_45_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_45_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd18a15bc49e87b8abc9231a13771a0fe34003b11fe1fd48df2d91f54bc40cc8 -size 15564 +oid sha256:3d5ed3a4c0340d904404c1ef68e7391e1303f865d15e88de6f82ed68e8dc4b4c +size 19463 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_46_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_46_en.png index 2ec96aeb8a..7024a8cc93 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_46_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_46_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:388a1ac9f1790fd305fd329b73ae621093d323db3fa4d4d32eef92f8dd5b51ec -size 14824 +oid sha256:c44464ab02dd9f1fc0624f2110bc9938c8aa8856bdad811aafa05eff2e144e4a +size 18884 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_47_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_47_en.png index c07dc719a8..a9d29c9fc3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_47_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_47_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc90e78d2fa94425322895028f1156bfda196ee2a761231920c6ffd80f02984b -size 17512 +oid sha256:57145b520f6702934571122f4c243f8740658847c0c60e6f901179d1d420d16a +size 20857 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_48_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_48_en.png index 33fa6946a2..a50251b367 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_48_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_48_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74fda6437495995876f76dc1ff0e056de4937ef8d719b3be1ce73baccd31516e -size 15889 +oid sha256:fd18a15bc49e87b8abc9231a13771a0fe34003b11fe1fd48df2d91f54bc40cc8 +size 15564 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_49_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_49_en.png index 2a2ed97c47..2ec96aeb8a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_49_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_49_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04fb2f230a09f0d3e27e151d98aa5d91e416b5ca9637b4db5d8e00118a68e7c4 -size 15166 +oid sha256:388a1ac9f1790fd305fd329b73ae621093d323db3fa4d4d32eef92f8dd5b51ec +size 14824 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_50_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_50_en.png index 233b0baf35..c07dc719a8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_50_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_50_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:896f698ef11d8a0577baf0a81cb54cabc307d95d05c230e5e3bdde40c3dc0900 -size 17844 +oid sha256:bc90e78d2fa94425322895028f1156bfda196ee2a761231920c6ffd80f02984b +size 17512 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_51_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_51_en.png index 20cd179751..33fa6946a2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_51_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_51_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf264b6f8af5b7432511d595ff8c663c5e2be33c9f85268627f5188e3f0f8db0 -size 18949 +oid sha256:74fda6437495995876f76dc1ff0e056de4937ef8d719b3be1ce73baccd31516e +size 15889 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_52_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_52_en.png index 304c73c954..2a2ed97c47 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_52_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_52_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0bbe1e3e8e1ea119cc61509617d3fa8e2bd047f619c41271901c73c46be1d610 -size 18201 +oid sha256:04fb2f230a09f0d3e27e151d98aa5d91e416b5ca9637b4db5d8e00118a68e7c4 +size 15166 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_53_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_53_en.png index 397c9c40c1..233b0baf35 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_53_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_53_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a7c183808801645e285dfba563c036c204a347de20b4b1e40fcfeab29fafb7d -size 20876 +oid sha256:896f698ef11d8a0577baf0a81cb54cabc307d95d05c230e5e3bdde40c3dc0900 +size 17844 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_54_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_54_en.png index 559903c1ac..20cd179751 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_54_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_54_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a48eb99f4466e3a883c0c7441006f201e0db22fd0e920ad0a77a8512637e01bb -size 16445 +oid sha256:cf264b6f8af5b7432511d595ff8c663c5e2be33c9f85268627f5188e3f0f8db0 +size 18949 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_55_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_55_en.png index 42cab93666..304c73c954 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_55_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_55_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:895ba9a35b8854d5005fc0671a7e6cbba5e26525b4a8ed4fa0fb612432caa04e -size 15205 +oid sha256:0bbe1e3e8e1ea119cc61509617d3fa8e2bd047f619c41271901c73c46be1d610 +size 18201 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_56_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_56_en.png index bb704942db..397c9c40c1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_56_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_56_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98baed819cd8b08085ceabf7dbccccc77b0fdf0d28a3f852879f6f8aa02ee441 -size 19848 +oid sha256:7a7c183808801645e285dfba563c036c204a347de20b4b1e40fcfeab29fafb7d +size 20876 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_57_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_57_en.png index 7f42bdc985..559903c1ac 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_57_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_57_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4678c15b608547c255d5eeb128c144ae7a3c5a21de2b047fc77f15364822ac2 -size 12847 +oid sha256:a48eb99f4466e3a883c0c7441006f201e0db22fd0e920ad0a77a8512637e01bb +size 16445 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_58_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_58_en.png index efb2ef5625..42cab93666 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_58_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_58_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e30395594c1a35d90fc0a04af340eb79cbe686d90856414d0024b769f86e89d -size 12507 +oid sha256:895ba9a35b8854d5005fc0671a7e6cbba5e26525b4a8ed4fa0fb612432caa04e +size 15205 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_59_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_59_en.png index d49a629afa..bb704942db 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_59_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_59_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60362244c7adf3644ed2ae354643e0525aad2a4454f6b13abce8fd265f4987c6 -size 13777 +oid sha256:98baed819cd8b08085ceabf7dbccccc77b0fdf0d28a3f852879f6f8aa02ee441 +size 19848 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_60_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_60_en.png index c7da5ce09d..7f42bdc985 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_60_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_60_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73de8ee7933c1a45a266761b14e09b008a62dc69b1600bbc69b8a01370fb97c1 -size 18641 +oid sha256:c4678c15b608547c255d5eeb128c144ae7a3c5a21de2b047fc77f15364822ac2 +size 12847 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_61_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_61_en.png index f9e9999e71..efb2ef5625 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_61_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_61_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b62b7dc22bfc727cfcbf7f6a19683bcf4da116c7192f9943f5addd11c39fcadb -size 17018 +oid sha256:5e30395594c1a35d90fc0a04af340eb79cbe686d90856414d0024b769f86e89d +size 12507 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_62_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_62_en.png index 0f4930cb81..d49a629afa 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_62_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_62_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0855112283bf797bc846e1982c6293e321361368481a803e12658723aaf8409 -size 22988 +oid sha256:60362244c7adf3644ed2ae354643e0525aad2a4454f6b13abce8fd265f4987c6 +size 13777 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_63_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_63_en.png index b7e63845b6..c7da5ce09d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_63_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_63_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:049b3ac784a8e400bad374a960ecb77d7f4bca81079be764dc74cb161f7a1093 -size 20880 +oid sha256:73de8ee7933c1a45a266761b14e09b008a62dc69b1600bbc69b8a01370fb97c1 +size 18641 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_64_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_64_en.png index 517de9d5bd..f9e9999e71 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_64_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_64_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21d83d719bee5fd19ad090791c7848890d87e4bd9eaddb17c9da1773ec81667f -size 19249 +oid sha256:b62b7dc22bfc727cfcbf7f6a19683bcf4da116c7192f9943f5addd11c39fcadb +size 17018 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_65_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_65_en.png index e39f788f2a..0f4930cb81 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_65_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_65_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:edc743a5cd067eb13e464f27c2f12f95433bd020dd1b3e920614ee913e06e476 -size 25008 +oid sha256:c0855112283bf797bc846e1982c6293e321361368481a803e12658723aaf8409 +size 22988 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_66_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_66_en.png index 71ba87addd..b7e63845b6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_66_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_66_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45e6821d622bfef22cc41a040e12e2b49e0bb50a88b0a143bdb25e3368809412 -size 16496 +oid sha256:049b3ac784a8e400bad374a960ecb77d7f4bca81079be764dc74cb161f7a1093 +size 20880 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_67_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_67_en.png index c00f6f274d..517de9d5bd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_67_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_67_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ddd2399d3d701fa962dc5683e054c2c4829ccd99d04498415ce88487f5e0ec8 -size 15760 +oid sha256:21d83d719bee5fd19ad090791c7848890d87e4bd9eaddb17c9da1773ec81667f +size 19249 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_68_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_68_en.png index c6917d9519..e39f788f2a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_68_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_68_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4293d98ed31f87c59ff5741344c2e41f58ff8f19c9342f6626553e978dbfc674 -size 18429 +oid sha256:edc743a5cd067eb13e464f27c2f12f95433bd020dd1b3e920614ee913e06e476 +size 25008 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_69_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_69_en.png index 439c8e754f..71ba87addd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_69_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_69_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37d1e302d4a610aaab7cfc6a15572b7eb92b059d9384e7bbe4daebcaf2da9049 -size 21343 +oid sha256:45e6821d622bfef22cc41a040e12e2b49e0bb50a88b0a143bdb25e3368809412 +size 16496 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_70_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_70_en.png index 19347bbaaa..c00f6f274d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_70_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_70_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:536d8d899945483352137d23356f3777db8e2225288f01e8cbcd1a770ca7f3ee -size 20494 +oid sha256:6ddd2399d3d701fa962dc5683e054c2c4829ccd99d04498415ce88487f5e0ec8 +size 15760 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_71_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_71_en.png index 3a5d6c57ad..c6917d9519 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_71_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_71_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:542b080ae9374e4f6d57689b1e1b6a84a0f81f017bd276bbcab43b9659be4335 -size 23534 +oid sha256:4293d98ed31f87c59ff5741344c2e41f58ff8f19c9342f6626553e978dbfc674 +size 18429 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_72_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_72_en.png index c116d68c19..439c8e754f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_72_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_72_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aeb02390258eade3ceb8c437bcf3592f3dde463d6f1b2a43ffefd61abf4184c4 -size 17236 +oid sha256:37d1e302d4a610aaab7cfc6a15572b7eb92b059d9384e7bbe4daebcaf2da9049 +size 21343 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_73_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_73_en.png index 04ec60caeb..19347bbaaa 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_73_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_73_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5c6bfe22fb71a9c6353718c2124000245182359ac1c43dfc8dd9b91415e66e6 -size 16385 +oid sha256:536d8d899945483352137d23356f3777db8e2225288f01e8cbcd1a770ca7f3ee +size 20494 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_74_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_74_en.png index e74e8a07b8..3a5d6c57ad 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_74_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_74_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:408f90e8a2f4dcd0716118fb522e5cd4adba0b2a429723fc2e47555b82acf005 -size 19501 +oid sha256:542b080ae9374e4f6d57689b1e1b6a84a0f81f017bd276bbcab43b9659be4335 +size 23534 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_75_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_75_en.png index 84b6c56c0e..c116d68c19 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_75_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_75_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9778edbbb33ab0bbaa0072bd4659488937efe0f8b8fac0a5b64497fe6a1e28e2 -size 20838 +oid sha256:aeb02390258eade3ceb8c437bcf3592f3dde463d6f1b2a43ffefd61abf4184c4 +size 17236 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_76_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_76_en.png index aa9b310163..04ec60caeb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_76_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_76_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97f43860bf9e65c7822943f8806a0642ce59957be5e35650e2b69a2c562a694c -size 18637 +oid sha256:d5c6bfe22fb71a9c6353718c2124000245182359ac1c43dfc8dd9b91415e66e6 +size 16385 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_77_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_77_en.png index 3e54c2ace5..e74e8a07b8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_77_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_77_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77e71b006b71300ccb1005ad3cac6a93ae242ff03f2936fdf9d10c0604d20faa -size 26121 +oid sha256:408f90e8a2f4dcd0716118fb522e5cd4adba0b2a429723fc2e47555b82acf005 +size 19501 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_78_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_78_en.png index b2eb2208d7..84b6c56c0e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_78_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_78_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e744d3fe3315dc6cb5beab80dc29d565500367772339071575b6505370e47207 -size 14771 +oid sha256:9778edbbb33ab0bbaa0072bd4659488937efe0f8b8fac0a5b64497fe6a1e28e2 +size 20838 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_79_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_79_en.png index 5dd29ba5c0..aa9b310163 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_79_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_79_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:448ea365e3e75059bc888961e3454562d35ab116c75b3b9855723b5fc1480d92 -size 14028 +oid sha256:97f43860bf9e65c7822943f8806a0642ce59957be5e35650e2b69a2c562a694c +size 18637 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_80_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_80_en.png index 4985f409fd..3e54c2ace5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_80_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_80_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad98105fcd6d6c02e5ae036ad49770b4aa35d94e32ab3a63f040deccc2375e6e -size 16703 +oid sha256:77e71b006b71300ccb1005ad3cac6a93ae242ff03f2936fdf9d10c0604d20faa +size 26121 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_81_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_81_en.png index e34b1d369a..b2eb2208d7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_81_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_81_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b8e747d51d6a6ab1ab6ff80224d0241a16f38b39e0c156dc6eef47ea56eca63 -size 18140 +oid sha256:e744d3fe3315dc6cb5beab80dc29d565500367772339071575b6505370e47207 +size 14771 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_82_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_82_en.png index fcf2962f34..5dd29ba5c0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_82_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_82_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34f28c6dbbe094b9ba070c6f1ef4b10b2625ea094629b6305dff70bdf6367ddc -size 16894 +oid sha256:448ea365e3e75059bc888961e3454562d35ab116c75b3b9855723b5fc1480d92 +size 14028 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_83_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_83_en.png index 8e996d615c..4985f409fd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_83_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_83_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccfe44da86dce16ba4816cfe2029c05d317fe29ca3bb816278f2bd929298d855 -size 21532 +oid sha256:ad98105fcd6d6c02e5ae036ad49770b4aa35d94e32ab3a63f040deccc2375e6e +size 16703 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_84_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_84_en.png index 54558de104..e34b1d369a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_84_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_84_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5b77bec92bc7c4da3fdc72831797d685bf042131c2222351cc7c852da48cd60 -size 17662 +oid sha256:5b8e747d51d6a6ab1ab6ff80224d0241a16f38b39e0c156dc6eef47ea56eca63 +size 18140 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_85_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_85_en.png index d36db47fcc..fcf2962f34 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_85_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_85_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:99f2b0e2fda05d6fa16c0f2dcc52e92f6fa1c656c6d84cf03e8507a5c14104e8 -size 16932 +oid sha256:34f28c6dbbe094b9ba070c6f1ef4b10b2625ea094629b6305dff70bdf6367ddc +size 16894 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_86_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_86_en.png index e0660d56c3..8e996d615c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_86_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_86_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e79cb41e125705af70990dec3e3fdc0a0202ec8d62f2077eb2a298243ae2e94d -size 19624 +oid sha256:ccfe44da86dce16ba4816cfe2029c05d317fe29ca3bb816278f2bd929298d855 +size 21532 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_87_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_87_en.png index bc91269c49..54558de104 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_87_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_87_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e0faccb345f65a543c56e4db44714614915a62b6916a77a0f4adfdae5215311e -size 15128 +oid sha256:e5b77bec92bc7c4da3fdc72831797d685bf042131c2222351cc7c852da48cd60 +size 17662 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_88_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_88_en.png index 259e239462..d36db47fcc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_88_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_88_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d626da2924325c074dcd2baf1c112430399553a9ee652cac03b0b1d3db4cff3 -size 14393 +oid sha256:99f2b0e2fda05d6fa16c0f2dcc52e92f6fa1c656c6d84cf03e8507a5c14104e8 +size 16932 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_89_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_89_en.png index 2082b4df3a..e0660d56c3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_89_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_89_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2be7c565d30e9f45a583b93ec948a7cb35a4bc872c4f479bd1efe9eda8972e7c -size 17044 +oid sha256:e79cb41e125705af70990dec3e3fdc0a0202ec8d62f2077eb2a298243ae2e94d +size 19624 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_90_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_90_en.png index 6dfa192fb9..bc91269c49 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_90_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_90_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c28eae20f614eae53e09aa4e396792f36ee1478c8141faad788fe397502da237 -size 20671 +oid sha256:e0faccb345f65a543c56e4db44714614915a62b6916a77a0f4adfdae5215311e +size 15128 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_91_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_91_en.png index b740d5c979..259e239462 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_91_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_91_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ada8d054436b15e9029150eb99e78103050f8d0428a1c78ef5667bfd54d3be5 -size 19195 +oid sha256:5d626da2924325c074dcd2baf1c112430399553a9ee652cac03b0b1d3db4cff3 +size 14393 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_92_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_92_en.png index 6b06753f70..2082b4df3a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_92_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_92_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7586db3dc8687c5c5fc73d28dd968041b192c160286f6a7c881eb7d86a2d1bd2 -size 24477 +oid sha256:2be7c565d30e9f45a583b93ec948a7cb35a4bc872c4f479bd1efe9eda8972e7c +size 17044 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_93_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_93_en.png index 42b0241e10..6dfa192fb9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_93_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_93_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ef75decb9f501eb6c1941e212e1b330203c16458bfc2e10bfac3d197b091a35 -size 17116 +oid sha256:c28eae20f614eae53e09aa4e396792f36ee1478c8141faad788fe397502da237 +size 20671 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_94_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_94_en.png index 04732e27fb..b740d5c979 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_94_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_94_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4940205ca9411e3175d24d7a45a49df77b2187318d4245d902db75230838e26f -size 15869 +oid sha256:8ada8d054436b15e9029150eb99e78103050f8d0428a1c78ef5667bfd54d3be5 +size 19195 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_95_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_95_en.png index a48e1ad7d3..6b06753f70 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_95_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_95_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1faa9029414b146707f2cd0d7c4899355cd196c3b5acd6e95ebe0d0bb599003 -size 20504 +oid sha256:7586db3dc8687c5c5fc73d28dd968041b192c160286f6a7c881eb7d86a2d1bd2 +size 24477 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_96_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_96_en.png index 3eeb6f47e4..42b0241e10 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_96_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_96_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90982bf0b723b89c9b070c1dc94eb5a9fcf66623c382d496174f026e053929fb -size 19493 +oid sha256:2ef75decb9f501eb6c1941e212e1b330203c16458bfc2e10bfac3d197b091a35 +size 17116 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_97_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_97_en.png index eee5b83831..04732e27fb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_97_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_97_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9640e8e6d758a03f995c7fbbb6c3c123109594138a7cc53d5416ef5e3e157693 -size 18006 +oid sha256:4940205ca9411e3175d24d7a45a49df77b2187318d4245d902db75230838e26f +size 15869 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_98_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_98_en.png index 70c84280d6..a48e1ad7d3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_98_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_98_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbe699fb17947981c53d47a9570da71e2388ec493a3a9471aaa13a5405075069 -size 23421 +oid sha256:a1faa9029414b146707f2cd0d7c4899355cd196c3b5acd6e95ebe0d0bb599003 +size 20504 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_99_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_99_en.png index f4e93c12ae..3eeb6f47e4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_99_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_99_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c6688901f89d3858ec67dda889fe589fb6b59202c64a4b700c2aa484e19f4cd -size 17606 +oid sha256:90982bf0b723b89c9b070c1dc94eb5a9fcf66623c382d496174f026e053929fb +size 19493 From cc38651c4477c9cbb19695b53f0e7341c0b7d3f6 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 23 Sep 2025 17:18:53 +0200 Subject: [PATCH 134/145] When joining a call, wait for the `content_loaded` action (#5399) * When joining a call, wait for the `content_loaded` action This ensures the widget won't be disposed when the user joins a call and loads the lobby screen for room calls --- .../features/call/impl/data/WidgetMessage.kt | 3 +++ .../features/call/impl/ui/CallScreenPresenter.kt | 16 ++++++++-------- .../features/call/ui/CallScreenPresenterTest.kt | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/data/WidgetMessage.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/data/WidgetMessage.kt index c18fef410e..5001d598d9 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/data/WidgetMessage.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/data/WidgetMessage.kt @@ -41,5 +41,8 @@ data class WidgetMessage( @SerialName("send_event") SendEvent, + + @SerialName("content_loaded") + ContentLoaded, } } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt index d82c64b607..c1c58d4607 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt @@ -79,7 +79,7 @@ class CallScreenPresenter( val urlState = remember { mutableStateOf>(AsyncData.Uninitialized) } val callWidgetDriver = remember { mutableStateOf(null) } val messageInterceptor = remember { mutableStateOf(null) } - var isJoinedCall by rememberSaveable { mutableStateOf(false) } + var isWidgetLoaded by rememberSaveable { mutableStateOf(false) } var ignoreWebViewError by rememberSaveable { mutableStateOf(false) } var webViewError by remember { mutableStateOf(null) } val languageTag = languageTagProvider.provideLanguageTag() @@ -139,8 +139,8 @@ class CallScreenPresenter( if (parsedMessage?.direction == WidgetMessage.Direction.FromWidget) { if (parsedMessage.action == WidgetMessage.Action.Close) { close(callWidgetDriver.value, navigator) - } else if (parsedMessage.action == WidgetMessage.Action.Join) { - isJoinedCall = true + } else if (parsedMessage.action == WidgetMessage.Action.ContentLoaded) { + isWidgetLoaded = true } } } @@ -151,8 +151,8 @@ class CallScreenPresenter( // Wait for the call to be joined, if it takes too long, we display an error delay(10.seconds) - if (!isJoinedCall) { - Timber.w("The call took too long to be joined. Displaying an error before exiting.") + if (!isWidgetLoaded) { + Timber.w("The call took too long to load. Displaying an error before exiting.") // This will display a simple 'Sorry, an error occurred' dialog and force the user to exit the call webViewError = "" @@ -165,10 +165,10 @@ class CallScreenPresenter( is CallScreenEvents.Hangup -> { val widgetId = callWidgetDriver.value?.id val interceptor = messageInterceptor.value - if (widgetId != null && interceptor != null && isJoinedCall) { + if (widgetId != null && interceptor != null && isWidgetLoaded) { // If the call was joined, we need to hang up first. Then the UI will be dismissed automatically. sendHangupMessage(widgetId, interceptor) - isJoinedCall = false + isWidgetLoaded = false coroutineScope.launch { // Wait for a couple of seconds to receive the hangup message @@ -198,7 +198,7 @@ class CallScreenPresenter( urlState = urlState.value, webViewError = webViewError, userAgent = userAgent, - isCallActive = isJoinedCall, + isCallActive = isWidgetLoaded, isInWidgetMode = isInWidgetMode, eventSink = { handleEvents(it) }, ) 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 15f1334773..47a91afa1c 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 @@ -215,7 +215,7 @@ import kotlin.time.Duration.Companion.seconds } @Test - fun `present - a received 'joined' action makes the call to be active`() = runTest { + fun `present - a received 'content loaded' action makes the call to be active`() = runTest { val navigator = FakeCallScreenNavigator() val widgetDriver = FakeMatrixWidgetDriver() val presenter = createCallScreenPresenter( @@ -238,7 +238,7 @@ import kotlin.time.Duration.Companion.seconds messageInterceptor.givenInterceptedMessage( """ { - "action":"io.element.join", + "action":"content_loaded", "api":"fromWidget", "widgetId":"1", "requestId":"1" From 8d3a6d3b6fa2625c0ee79de364f842edcb68af2f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 23 Sep 2025 21:24:38 +0200 Subject: [PATCH 135/145] Extract topbars from MessagesView to reduce this file size. No code change. --- .../features/messages/impl/MessagesView.kt | 229 +----------------- .../impl/topbars/MessagesViewTopBar.kt | 143 +++++++++++ .../messages/impl/topbars/ThreadTopBar.kt | 143 +++++++++++ 3 files changed, 288 insertions(+), 227 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.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 1cc84eee78..07fc178721 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 @@ -11,12 +11,10 @@ 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 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.WindowInsets import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize @@ -27,30 +25,23 @@ import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.systemBarsPadding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role -import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme -import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.api.timeline.voicemessages.composer.VoiceMessageComposerEvents import io.element.android.features.messages.impl.actionlist.ActionListEvents import io.element.android.features.messages.impl.actionlist.ActionListView @@ -69,7 +60,6 @@ import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBan 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.CallMenuItem import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvents import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents @@ -77,30 +67,23 @@ import io.element.android.features.messages.impl.timeline.components.reactionsum import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheet 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.topbars.MessagesViewTopBar +import io.element.android.features.messages.impl.topbars.ThreadTopBar import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessagePermissionRationaleDialog import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageSendingFailedDialog import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView -import io.element.android.features.roomcall.api.RoomCallState import io.element.android.libraries.androidutils.ui.hideKeyboard import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertMolecule import io.element.android.libraries.designsystem.components.ExpandableBottomSheetLayout import io.element.android.libraries.designsystem.components.ExpandableBottomSheetLayoutState -import io.element.android.libraries.designsystem.components.avatar.Avatar -import io.element.android.libraries.designsystem.components.avatar.AvatarData -import io.element.android.libraries.designsystem.components.avatar.AvatarSize -import io.element.android.libraries.designsystem.components.avatar.AvatarType -import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.rememberExpandableBottomSheetLayoutState import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.toAnnotatedString import io.element.android.libraries.designsystem.theme.components.BottomSheetDragHandle -import io.element.android.libraries.designsystem.theme.components.HorizontalDivider -import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.utils.HideKeyboardWhenDisposed import io.element.android.libraries.designsystem.utils.KeepScreenOn import io.element.android.libraries.designsystem.utils.OnLifecycleEvent @@ -113,14 +96,9 @@ import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.matrix.ui.components.aMatrixUserList -import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.textcomposer.model.TextEditorState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.wysiwyg.link.Link -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toImmutableList import timber.log.Timber import kotlin.time.Duration.Companion.milliseconds @@ -517,154 +495,6 @@ private fun MessagesViewComposerBottomSheetContents( } } -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun MessagesViewTopBar( - roomName: String?, - roomAvatar: AvatarData, - isTombstoned: Boolean, - heroes: ImmutableList, - roomCallState: RoomCallState, - dmUserIdentityState: IdentityState?, - onRoomDetailsClick: () -> Unit, - onJoinCallClick: () -> Unit, - onBackClick: () -> Unit, -) { - TopAppBar( - navigationIcon = { - BackButton(onClick = onBackClick) - }, - title = { - val roundedCornerShape = RoundedCornerShape(8.dp) - Row( - modifier = Modifier - .clip(roundedCornerShape) - .clickable { onRoomDetailsClick() }, - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - val titleModifier = Modifier.weight(1f, fill = false) - RoomAvatarAndNameRow( - roomName = roomName, - roomAvatar = roomAvatar, - isTombstoned = isTombstoned, - heroes = heroes, - modifier = titleModifier - ) - - when (dmUserIdentityState) { - IdentityState.Verified -> { - Icon( - imageVector = CompoundIcons.Verified(), - tint = ElementTheme.colors.iconSuccessPrimary, - contentDescription = null, - ) - } - IdentityState.VerificationViolation -> { - Icon( - imageVector = CompoundIcons.ErrorSolid(), - tint = ElementTheme.colors.iconCriticalPrimary, - contentDescription = null, - ) - } - else -> Unit - } - } - }, - actions = { - CallMenuItem( - roomCallState = roomCallState, - onJoinCallClick = onJoinCallClick, - ) - Spacer(Modifier.width(8.dp)) - }, - windowInsets = WindowInsets(0.dp) - ) -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun ThreadTopBar( - roomName: String?, - roomAvatarData: AvatarData, - heroes: ImmutableList, - isTombstoned: Boolean, - onBackClick: () -> Unit, - modifier: Modifier = Modifier, -) { - TopAppBar( - modifier = modifier, - navigationIcon = { - BackButton(onClick = onBackClick) - }, - title = { - Row(verticalAlignment = Alignment.CenterVertically) { - Avatar( - avatarData = roomAvatarData, - avatarType = AvatarType.Room( - heroes = heroes, - isTombstoned = isTombstoned, - ), - ) - Column( - modifier = Modifier.fillMaxWidth() - .padding(horizontal = 8.dp) - .semantics { - heading() - }, - ) { - Text( - text = stringResource(CommonStrings.common_thread), - style = ElementTheme.typography.fontBodyLgMedium, - ) - Text( - text = roomName ?: stringResource(CommonStrings.common_no_room_name), - style = ElementTheme.typography.fontBodySmRegular, - fontStyle = FontStyle.Italic.takeIf { roomName == null }, - color = ElementTheme.colors.textSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - } - } - ) -} - -@Composable -private fun RoomAvatarAndNameRow( - roomName: String?, - roomAvatar: AvatarData, - heroes: ImmutableList, - isTombstoned: Boolean, - modifier: Modifier = Modifier -) { - Row( - modifier = modifier, - verticalAlignment = Alignment.CenterVertically - ) { - Avatar( - avatarData = roomAvatar, - avatarType = AvatarType.Room( - heroes = heroes, - isTombstoned = isTombstoned, - ), - ) - Text( - modifier = Modifier - .padding(horizontal = 8.dp) - .semantics { - heading() - }, - text = roomName ?: stringResource(CommonStrings.common_no_room_name), - style = ElementTheme.typography.fontBodyLgMedium, - fontStyle = FontStyle.Italic.takeIf { roomName == null }, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } -} - @Composable private fun CantSendMessageBanner() { Row( @@ -719,58 +549,3 @@ internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class) knockRequestsBannerView = {}, ) } - -@PreviewsDayNight -@Composable -internal fun ThreadTopBarPreview() { - ElementPreview { - val name = "Room name" - val initialsAvatarData = AvatarData( - id = "id", - name = name, - url = null, - size = AvatarSize.TimelineRoom, - ) - Column { - ThreadTopBar( - roomName = name, - roomAvatarData = initialsAvatarData, - heroes = persistentListOf(), - isTombstoned = false, - onBackClick = {}, - ) - HorizontalDivider() - ThreadTopBar( - roomName = name, - roomAvatarData = initialsAvatarData, - heroes = aMatrixUserList().map { it.getAvatarData(AvatarSize.TimelineRoom) }.toImmutableList(), - isTombstoned = false, - onBackClick = {}, - ) - HorizontalDivider() - ThreadTopBar( - roomName = null, - roomAvatarData = initialsAvatarData, - heroes = persistentListOf(), - isTombstoned = false, - onBackClick = {}, - ) - HorizontalDivider() - ThreadTopBar( - roomName = name, - roomAvatarData = initialsAvatarData.copy(url = "https://some-avatar.jpg"), - heroes = persistentListOf(), - isTombstoned = false, - onBackClick = {}, - ) - HorizontalDivider() - ThreadTopBar( - roomName = name, - roomAvatarData = initialsAvatarData, - heroes = persistentListOf(), - isTombstoned = true, - onBackClick = {}, - ) - } - } -} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt new file mode 100644 index 0000000000..a65f732576 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -0,0 +1,143 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.topbars + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.heading +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.style.TextOverflow +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.CallMenuItem +import io.element.android.features.roomcall.api.RoomCallState +import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarType +import io.element.android.libraries.designsystem.components.button.BackButton +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.TopAppBar +import io.element.android.libraries.matrix.api.encryption.identity.IdentityState +import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.ImmutableList + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun MessagesViewTopBar( + roomName: String?, + roomAvatar: AvatarData, + isTombstoned: Boolean, + heroes: ImmutableList, + roomCallState: RoomCallState, + dmUserIdentityState: IdentityState?, + onRoomDetailsClick: () -> Unit, + onJoinCallClick: () -> Unit, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + TopAppBar( + modifier = modifier, + navigationIcon = { + BackButton(onClick = onBackClick) + }, + title = { + val roundedCornerShape = RoundedCornerShape(8.dp) + Row( + modifier = Modifier + .clip(roundedCornerShape) + .clickable { onRoomDetailsClick() }, + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + val titleModifier = Modifier.weight(1f, fill = false) + RoomAvatarAndNameRow( + roomName = roomName, + roomAvatar = roomAvatar, + isTombstoned = isTombstoned, + heroes = heroes, + modifier = titleModifier + ) + + when (dmUserIdentityState) { + IdentityState.Verified -> { + Icon( + imageVector = CompoundIcons.Verified(), + tint = ElementTheme.colors.iconSuccessPrimary, + contentDescription = null, + ) + } + IdentityState.VerificationViolation -> { + Icon( + imageVector = CompoundIcons.ErrorSolid(), + tint = ElementTheme.colors.iconCriticalPrimary, + contentDescription = null, + ) + } + else -> Unit + } + } + }, + actions = { + CallMenuItem( + roomCallState = roomCallState, + onJoinCallClick = onJoinCallClick, + ) + Spacer(Modifier.width(8.dp)) + }, + windowInsets = WindowInsets(0.dp) + ) +} + +@Composable +private fun RoomAvatarAndNameRow( + roomName: String?, + roomAvatar: AvatarData, + heroes: ImmutableList, + isTombstoned: Boolean, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically + ) { + Avatar( + avatarData = roomAvatar, + avatarType = AvatarType.Room( + heroes = heroes, + isTombstoned = isTombstoned, + ), + ) + Text( + modifier = Modifier + .padding(horizontal = 8.dp) + .semantics { + heading() + }, + text = roomName ?: stringResource(CommonStrings.common_no_room_name), + style = ElementTheme.typography.fontBodyLgMedium, + fontStyle = FontStyle.Italic.takeIf { roomName == null }, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt new file mode 100644 index 0000000000..b2c8f9758d --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt @@ -0,0 +1,143 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.topbars + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.heading +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.AvatarType +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.HorizontalDivider +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.matrix.ui.components.aMatrixUserList +import io.element.android.libraries.matrix.ui.model.getAvatarData +import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun ThreadTopBar( + roomName: String?, + roomAvatarData: AvatarData, + heroes: ImmutableList, + isTombstoned: Boolean, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + TopAppBar( + modifier = modifier, + navigationIcon = { + BackButton(onClick = onBackClick) + }, + title = { + Row(verticalAlignment = Alignment.CenterVertically) { + Avatar( + avatarData = roomAvatarData, + avatarType = AvatarType.Room( + heroes = heroes, + isTombstoned = isTombstoned, + ), + ) + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 8.dp) + .semantics { + heading() + }, + ) { + Text( + text = stringResource(CommonStrings.common_thread), + style = ElementTheme.typography.fontBodyLgMedium, + ) + Text( + text = roomName ?: stringResource(CommonStrings.common_no_room_name), + style = ElementTheme.typography.fontBodySmRegular, + fontStyle = FontStyle.Italic.takeIf { roomName == null }, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } + ) +} + +@PreviewsDayNight +@Composable +internal fun ThreadTopBarPreview() = ElementPreview { + val name = "Room name" + val initialsAvatarData = AvatarData( + id = "id", + name = name, + url = null, + size = AvatarSize.TimelineRoom, + ) + Column { + ThreadTopBar( + roomName = name, + roomAvatarData = initialsAvatarData, + heroes = persistentListOf(), + isTombstoned = false, + onBackClick = {}, + ) + HorizontalDivider() + ThreadTopBar( + roomName = name, + roomAvatarData = initialsAvatarData, + heroes = aMatrixUserList().map { it.getAvatarData(AvatarSize.TimelineRoom) }.toImmutableList(), + isTombstoned = false, + onBackClick = {}, + ) + HorizontalDivider() + ThreadTopBar( + roomName = null, + roomAvatarData = initialsAvatarData, + heroes = persistentListOf(), + isTombstoned = false, + onBackClick = {}, + ) + HorizontalDivider() + ThreadTopBar( + roomName = name, + roomAvatarData = initialsAvatarData.copy(url = "https://some-avatar.jpg"), + heroes = persistentListOf(), + isTombstoned = false, + onBackClick = {}, + ) + HorizontalDivider() + ThreadTopBar( + roomName = name, + roomAvatarData = initialsAvatarData, + heroes = persistentListOf(), + isTombstoned = true, + onBackClick = {}, + ) + } +} From b3dd6a257ec74a429b890fd33c67989427192114 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 23 Sep 2025 21:41:13 +0200 Subject: [PATCH 136/145] Reduce number of previews of MessagesView and create preview dedicated to MessagesViewTopBar. --- .../messages/impl/MessagesStateProvider.kt | 9 --- .../impl/topbars/MessagesViewTopBar.kt | 70 +++++++++++++++++++ 2 files changed, 70 insertions(+), 9 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 8217cb977c..6284cf45ad 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 @@ -60,31 +60,22 @@ open class MessagesStateProvider : PreviewParameterProvider { aMessagesState(composerState = aMessageComposerState(showAttachmentSourcePicker = true)), aMessagesState(userEventPermissions = aUserEventPermissions(canSendMessage = false)), aMessagesState(showReinvitePrompt = true), - aMessagesState(roomName = null), aMessagesState(composerState = aMessageComposerState(showTextFormatting = true)), aMessagesState( voiceMessageComposerState = aVoiceMessageComposerState(showPermissionRationaleDialog = true), ), - aMessagesState( - roomCallState = anOngoingCallState(), - ), aMessagesState( voiceMessageComposerState = aVoiceMessageComposerState( voiceMessageState = aVoiceMessagePreviewState(), showSendFailureDialog = true ), ), - aMessagesState( - roomCallState = aStandByCallState(canStartCall = false), - ), aMessagesState( pinnedMessagesBannerState = aLoadedPinnedMessagesBannerState( knownPinnedMessagesCount = 4, currentPinnedMessageIndex = 0, ), ), - aMessagesState(roomName = "A DM with a very looong name", dmUserVerificationState = IdentityState.Verified), - aMessagesState(roomName = "A DM with a very looong name", dmUserVerificationState = IdentityState.VerificationViolation), aMessagesState(successorRoom = SuccessorRoom(RoomId("!id:domain"), null)), aMessagesState(timelineState = aTimelineState( timelineMode = Timeline.Mode.Thread(threadRootId = ThreadId("\$a-thread-id")), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt index a65f732576..570cf98529 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -9,6 +9,7 @@ package io.element.android.features.messages.impl.topbars import androidx.compose.foundation.clickable 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.WindowInsets @@ -30,16 +31,25 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.impl.timeline.components.CallMenuItem import io.element.android.features.roomcall.api.RoomCallState +import io.element.android.features.roomcall.api.aStandByCallState +import io.element.android.features.roomcall.api.anOngoingCallState import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType 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.HorizontalDivider 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.TopAppBar import io.element.android.libraries.matrix.api.encryption.identity.IdentityState +import io.element.android.libraries.matrix.ui.components.aMatrixUserList +import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -141,3 +151,63 @@ private fun RoomAvatarAndNameRow( ) } } + +@PreviewsDayNight +@Composable +internal fun MessagesViewTopBarPreview() = ElementPreview { + @Composable + fun AMessagesViewTopBar( + roomName: String? = "Room name", + roomAvatar: AvatarData = AvatarData( + id = "id", + name = "Room name", + url = null, + size = AvatarSize.TimelineRoom, + ), + isTombstoned: Boolean = false, + heroes: List = emptyList(), + roomCallState: RoomCallState = RoomCallState.Unavailable, + dmUserIdentityState: IdentityState? = null, + ) = MessagesViewTopBar( + roomName = roomName, + roomAvatar = roomAvatar, + isTombstoned = isTombstoned, + heroes = heroes.toImmutableList(), + roomCallState = roomCallState, + dmUserIdentityState = dmUserIdentityState, + onRoomDetailsClick = {}, + onJoinCallClick = {}, + onBackClick = {}, + ) + Column { + AMessagesViewTopBar() + HorizontalDivider() + AMessagesViewTopBar( + heroes = aMatrixUserList().map { it.getAvatarData(AvatarSize.TimelineRoom) }, + roomCallState = anOngoingCallState(), + ) + HorizontalDivider() + AMessagesViewTopBar( + roomName = null, + roomCallState = anOngoingCallState(canJoinCall = false), + ) + HorizontalDivider() + AMessagesViewTopBar( + roomName = "A DM with a very very very long name", + roomAvatar = AvatarData( + id = "id", + name = "Room name", + url = null, + size = AvatarSize.TimelineRoom, + ).copy(url = "https://some-avatar.jpg"), + roomCallState = aStandByCallState(canStartCall = false), + dmUserIdentityState = IdentityState.Verified + ) + HorizontalDivider() + AMessagesViewTopBar( + roomName = "A DM with a very very very long name", + isTombstoned = true, + dmUserIdentityState = IdentityState.VerificationViolation + ) + } +} From 164149e76bd57181475b9f9f67edf51521e01750 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 23 Sep 2025 21:47:43 +0200 Subject: [PATCH 137/145] More cleanup --- .../impl/topbars/MessagesViewTopBar.kt | 13 ++-- .../messages/impl/topbars/ThreadTopBar.kt | 61 ++++++++----------- 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt index 570cf98529..c66170596b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -37,6 +37,7 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType +import io.element.android.libraries.designsystem.components.avatar.anAvatarData 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 @@ -158,10 +159,8 @@ internal fun MessagesViewTopBarPreview() = ElementPreview { @Composable fun AMessagesViewTopBar( roomName: String? = "Room name", - roomAvatar: AvatarData = AvatarData( - id = "id", + roomAvatar: AvatarData = anAvatarData( name = "Room name", - url = null, size = AvatarSize.TimelineRoom, ), isTombstoned: Boolean = false, @@ -194,12 +193,10 @@ internal fun MessagesViewTopBarPreview() = ElementPreview { HorizontalDivider() AMessagesViewTopBar( roomName = "A DM with a very very very long name", - roomAvatar = AvatarData( - id = "id", - name = "Room name", - url = null, + roomAvatar = anAvatarData( size = AvatarSize.TimelineRoom, - ).copy(url = "https://some-avatar.jpg"), + url = "https://some-avatar.jpg" + ), roomCallState = aStandByCallState(canStartCall = false), dmUserIdentityState = IdentityState.Verified ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt index b2c8f9758d..3b3890bd23 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt @@ -26,6 +26,7 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType +import io.element.android.libraries.designsystem.components.avatar.anAvatarData 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 @@ -36,7 +37,6 @@ import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @OptIn(ExperimentalMaterial3Api::class) @@ -92,52 +92,43 @@ internal fun ThreadTopBar( @PreviewsDayNight @Composable internal fun ThreadTopBarPreview() = ElementPreview { - val name = "Room name" - val initialsAvatarData = AvatarData( - id = "id", - name = name, - url = null, - size = AvatarSize.TimelineRoom, + @Composable + fun AThreadTopBar( + roomName: String? = "Room name", + roomAvatarData: AvatarData = anAvatarData( + name = "Room name", + size = AvatarSize.TimelineRoom, + ), + isTombstoned: Boolean = false, + heroes: List = emptyList(), + ) = ThreadTopBar( + roomName = roomName, + roomAvatarData = roomAvatarData, + isTombstoned = isTombstoned, + heroes = heroes.toImmutableList(), + onBackClick = {}, ) Column { - ThreadTopBar( - roomName = name, - roomAvatarData = initialsAvatarData, - heroes = persistentListOf(), - isTombstoned = false, - onBackClick = {}, - ) + AThreadTopBar() HorizontalDivider() - ThreadTopBar( - roomName = name, - roomAvatarData = initialsAvatarData, + AThreadTopBar( heroes = aMatrixUserList().map { it.getAvatarData(AvatarSize.TimelineRoom) }.toImmutableList(), - isTombstoned = false, - onBackClick = {}, ) HorizontalDivider() - ThreadTopBar( + AThreadTopBar( roomName = null, - roomAvatarData = initialsAvatarData, - heroes = persistentListOf(), - isTombstoned = false, - onBackClick = {}, ) HorizontalDivider() - ThreadTopBar( - roomName = name, - roomAvatarData = initialsAvatarData.copy(url = "https://some-avatar.jpg"), - heroes = persistentListOf(), - isTombstoned = false, - onBackClick = {}, + AThreadTopBar( + roomAvatarData = anAvatarData( + name = "Room name", + url = "https://some-avatar.jpg", + size = AvatarSize.TimelineRoom, + ), ) HorizontalDivider() - ThreadTopBar( - roomName = name, - roomAvatarData = initialsAvatarData, - heroes = persistentListOf(), + AThreadTopBar( isTombstoned = true, - onBackClick = {}, ) } } From 4dfb9a32b8101a2b106fc1b11e09dc16496cd521 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 23 Sep 2025 21:51:26 +0200 Subject: [PATCH 138/145] More cleanup --- .../features/messages/impl/MessagesStateProvider.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 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 6284cf45ad..e20526d083 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 @@ -36,7 +36,6 @@ import io.element.android.features.messages.impl.timeline.protection.TimelinePro import io.element.android.features.messages.impl.timeline.protection.aTimelineProtectionState import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomcall.api.aStandByCallState -import io.element.android.features.roomcall.api.anOngoingCallState import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncData @@ -77,10 +76,12 @@ open class MessagesStateProvider : PreviewParameterProvider { ), ), aMessagesState(successorRoom = SuccessorRoom(RoomId("!id:domain"), null)), - aMessagesState(timelineState = aTimelineState( - timelineMode = Timeline.Mode.Thread(threadRootId = ThreadId("\$a-thread-id")), - timelineItems = aTimelineItemList(aTimelineItemTextContent()), - )), + aMessagesState( + timelineState = aTimelineState( + timelineMode = Timeline.Mode.Thread(threadRootId = ThreadId("\$a-thread-id")), + timelineItems = aTimelineItemList(aTimelineItemTextContent()), + ) + ), ) } From e36c9b7b88774320bdd0a681b68e3dc87d9da75d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 23 Sep 2025 21:56:03 +0200 Subject: [PATCH 139/145] More cleanup --- .../features/messages/impl/topbars/MessagesViewTopBar.kt | 7 ++++--- .../android/features/messages/impl/topbars/ThreadTopBar.kt | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt index c66170596b..62c9c3e206 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -50,6 +50,7 @@ import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @OptIn(ExperimentalMaterial3Api::class) @@ -164,14 +165,14 @@ internal fun MessagesViewTopBarPreview() = ElementPreview { size = AvatarSize.TimelineRoom, ), isTombstoned: Boolean = false, - heroes: List = emptyList(), + heroes: ImmutableList = persistentListOf(), roomCallState: RoomCallState = RoomCallState.Unavailable, dmUserIdentityState: IdentityState? = null, ) = MessagesViewTopBar( roomName = roomName, roomAvatar = roomAvatar, isTombstoned = isTombstoned, - heroes = heroes.toImmutableList(), + heroes = heroes, roomCallState = roomCallState, dmUserIdentityState = dmUserIdentityState, onRoomDetailsClick = {}, @@ -182,7 +183,7 @@ internal fun MessagesViewTopBarPreview() = ElementPreview { AMessagesViewTopBar() HorizontalDivider() AMessagesViewTopBar( - heroes = aMatrixUserList().map { it.getAvatarData(AvatarSize.TimelineRoom) }, + heroes = aMatrixUserList().map { it.getAvatarData(AvatarSize.TimelineRoom) }.toImmutableList(), roomCallState = anOngoingCallState(), ) HorizontalDivider() diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt index 3b3890bd23..5a95c2c4b2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt @@ -37,6 +37,7 @@ import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @OptIn(ExperimentalMaterial3Api::class) @@ -100,12 +101,12 @@ internal fun ThreadTopBarPreview() = ElementPreview { size = AvatarSize.TimelineRoom, ), isTombstoned: Boolean = false, - heroes: List = emptyList(), + heroes: ImmutableList = persistentListOf(), ) = ThreadTopBar( roomName = roomName, roomAvatarData = roomAvatarData, isTombstoned = isTombstoned, - heroes = heroes.toImmutableList(), + heroes = heroes, onBackClick = {}, ) Column { From 321c5f64979d98452dd22e12c68fbf88265948c7 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 23 Sep 2025 20:12:48 +0000 Subject: [PATCH 140/145] Update screenshots --- ...ures.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png | 3 +++ ...es.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png | 3 +++ .../features.messages.impl.topbars_ThreadTopBar_Day_0_en.png | 3 +++ ...features.messages.impl.topbars_ThreadTopBar_Night_0_en.png | 3 +++ .../images/features.messages.impl_MessagesView_Day_10_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_11_en.png | 3 --- .../images/features.messages.impl_MessagesView_Day_12_en.png | 3 --- .../images/features.messages.impl_MessagesView_Day_13_en.png | 3 --- .../images/features.messages.impl_MessagesView_Day_14_en.png | 3 --- .../images/features.messages.impl_MessagesView_Day_15_en.png | 3 --- .../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 ++-- .../features.messages.impl_MessagesView_Night_10_en.png | 4 ++-- .../features.messages.impl_MessagesView_Night_11_en.png | 3 --- .../features.messages.impl_MessagesView_Night_12_en.png | 3 --- .../features.messages.impl_MessagesView_Night_13_en.png | 3 --- .../features.messages.impl_MessagesView_Night_14_en.png | 3 --- .../features.messages.impl_MessagesView_Night_15_en.png | 3 --- .../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 ++-- .../images/features.messages.impl_ThreadTopBar_Day_0_en.png | 3 --- .../images/features.messages.impl_ThreadTopBar_Night_0_en.png | 3 --- 28 files changed, 36 insertions(+), 60 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_ThreadTopBar_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_ThreadTopBar_Night_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_12_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_13_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_14_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_15_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_12_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_13_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_14_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_15_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png new file mode 100644 index 0000000000..571661e434 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:065466dc414d77a58f2d22c26fc9d5e9b7afe5d5206cdbcc2bbdc6e8ea192d15 +size 40479 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png new file mode 100644 index 0000000000..958d12766d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c34b8c47d89231b8e5660726d63b94e3e8b97a2fc7e0b615f8f9e2d61066470 +size 39172 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_ThreadTopBar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_ThreadTopBar_Day_0_en.png new file mode 100644 index 0000000000..079ac780f8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_ThreadTopBar_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:617a819de3cd223323b0fa1853185ceb26ffb97a22d79524acec0f4d5b3a634b +size 33550 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_ThreadTopBar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_ThreadTopBar_Night_0_en.png new file mode 100644 index 0000000000..b3f0e9c13e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_ThreadTopBar_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e146eee5e94e29a2b87b3d4a9bf248445e08dc6eb68c2268b6f263533675c78 +size 33050 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 94548f50d8..11b3313094 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:e1ffac0c95378fa7778a4d5b3e5af5a47eef44757f13dbe0032d30b30f96561b -size 58549 +oid sha256:9571176fb73b9871b6db3c30679a46c776badb56d4e1919ea882b391d893b8c4 +size 53144 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 deleted file mode 100644 index 4ab2179c6b..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:983db5846ee050f682b895ef0ce54362b1214c5bee48ef94139ef825e0ecbab6 -size 61678 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 deleted file mode 100644 index 788ff1abe6..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_12_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:501b8bc5c6163c85d1aaee4c9b81c56610931b6d693421d87b5107b3389170ea -size 60829 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 deleted file mode 100644 index 25a8d03e4a..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_13_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b116183b02d89b112d35ae86d68fdfcec0cb63e5ded20c611a152836090b19b2 -size 60755 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_14_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_14_en.png deleted file mode 100644 index 22fda1dd27..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_14_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0fd783aa6c219e5bdc3c03579bd823a286e6048581728a6786ee724ef458050c -size 63807 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_15_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_15_en.png deleted file mode 100644 index 11b3313094..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_15_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9571176fb73b9871b6db3c30679a46c776badb56d4e1919ea882b391d893b8c4 -size 53144 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 abd6861f7e..657dc6d2ac 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:373b60146f1fe215eea0c559fbe9810bfe9b714f021e3dddbb649dd6105c5f43 -size 59547 +oid sha256:f6a08f9b69ec278f8706c8de459fd6d2747cef7ed51da32eb7239667d0805e58 +size 55311 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 657dc6d2ac..3d2d2949ab 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:f6a08f9b69ec278f8706c8de459fd6d2747cef7ed51da32eb7239667d0805e58 -size 55311 +oid sha256:1b298a6432190f54fdb824c7edc2f8cda30a746d2a13322793c84a5a3d42f5ea +size 59985 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 3d2d2949ab..e3b8e08ac7 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:1b298a6432190f54fdb824c7edc2f8cda30a746d2a13322793c84a5a3d42f5ea -size 59985 +oid sha256:61add48c03d1f4df4bc9010826c4a6f5adaa312ef5f910bc0b3a77211a377f66 +size 50651 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 8c8344673d..4ab2179c6b 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:34a70e62b687f5726073a2339a4246f0e6bf31c187483829082612be69938087 -size 60107 +oid sha256:983db5846ee050f682b895ef0ce54362b1214c5bee48ef94139ef825e0ecbab6 +size 61678 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 e3b8e08ac7..22fda1dd27 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:61add48c03d1f4df4bc9010826c4a6f5adaa312ef5f910bc0b3a77211a377f66 -size 50651 +oid sha256:0fd783aa6c219e5bdc3c03579bd823a286e6048581728a6786ee724ef458050c +size 63807 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 68918896b2..7d33111f68 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:edc830108c2dd54d594a383020c2e73dba6b6fdff44e279b87889f3dc84ea546 -size 56308 +oid sha256:d6ea6d7eb98c546dbee109d160e2adbbbd4d22d4844835667bfbab1de2060115 +size 52351 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 deleted file mode 100644 index 0ef6da37c9..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bf12305ee99f199905e94e325743b1589f11d36815e16e86558691400e2991e3 -size 59022 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 deleted file mode 100644 index 98512acaa5..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_12_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e1b50937116f9d14103a1753199686f959371b8fe6ad006cadf1c3fb121fb72a -size 58491 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 deleted file mode 100644 index 9ed7763072..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_13_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8f5c6283d080341dd600f723329355447fa190c8b36aa4241536c4993ce55b76 -size 58466 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_14_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_14_en.png deleted file mode 100644 index 998c5ab138..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_14_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:01ea3893df495012f2e417e81d2223696ee11efe2499c0c2a112f015c1f72f7a -size 64610 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_15_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_15_en.png deleted file mode 100644 index 7d33111f68..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_15_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d6ea6d7eb98c546dbee109d160e2adbbbd4d22d4844835667bfbab1de2060115 -size 52351 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 06f314231c..c041fd7d11 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:21ef350495865cd55510b9dd59ffcb7fa3600369df3077322c352e47cc8d93b1 -size 57291 +oid sha256:c1534b9c3b6952c290ca20a2853e56be023e5c8129a10b9f3fd63c290c7ba9fb +size 52977 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 c041fd7d11..7a6efabb58 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:c1534b9c3b6952c290ca20a2853e56be023e5c8129a10b9f3fd63c290c7ba9fb -size 52977 +oid sha256:7b50e874595cfcb65cf2a4f7146ed7c99ee06899d6512024b900a64439748a6f +size 54078 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 7a6efabb58..21888106d2 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:7b50e874595cfcb65cf2a4f7146ed7c99ee06899d6512024b900a64439748a6f -size 54078 +oid sha256:aafdc477f090674d0473076071049bba77bc57025c602cb6bc1cdfada03a1937 +size 44740 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 2745c0ff60..0ef6da37c9 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:b5052598f1d095bb854522a2b0e880a6a88c070e372e1a2fd73b487611f8f733 -size 57716 +oid sha256:bf12305ee99f199905e94e325743b1589f11d36815e16e86558691400e2991e3 +size 59022 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 21888106d2..998c5ab138 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:aafdc477f090674d0473076071049bba77bc57025c602cb6bc1cdfada03a1937 -size 44740 +oid sha256:01ea3893df495012f2e417e81d2223696ee11efe2499c0c2a112f015c1f72f7a +size 64610 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Day_0_en.png deleted file mode 100644 index 29d2a7fee4..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:10ef1d5b008da94cdf48525d98bdb1e10f6013124c499f67c9fcd39bee85b7aa -size 33773 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Night_0_en.png deleted file mode 100644 index 6a5b231305..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_ThreadTopBar_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d98bfa7c506d089ae16b2f35ffa4e189ae1a31ca114333d755fd837b13128759 -size 32921 From d391be7002dad4c2e0ff1f9df99e28e09dcccc78 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 24 Sep 2025 10:16:42 +0200 Subject: [PATCH 141/145] Ensure the thread summary sender display name won't wrap to the next line (#5403) --- .../messages/impl/timeline/components/TimelineItemEventRow.kt | 2 ++ 1 file changed, 2 insertions(+) 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 fb45278b78..1503bf236b 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 @@ -352,6 +352,8 @@ private fun ThreadSummaryView( text = latestEvent.senderProfile.getDisambiguatedDisplayName(latestEvent.senderId), style = ElementTheme.typography.fontBodySmMedium, color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, ) Spacer(modifier = Modifier.width(4.dp)) From f3a9646db2b3a749aa54b816556bafaca40cdb37 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 24 Sep 2025 09:36:41 +0000 Subject: [PATCH 142/145] Update screenshots --- .../images/features.space.impl_SpaceView_Day_1_en.png | 4 ++-- .../images/features.space.impl_SpaceView_Night_1_en.png | 4 ++-- ....designsystem.components.avatar_Avatar_Avatars_102_en.png | 5 +++-- ....designsystem.components.avatar_Avatar_Avatars_103_en.png | 5 +++-- ....designsystem.components.avatar_Avatar_Avatars_104_en.png | 5 +++-- ....designsystem.components.avatar_Avatar_Avatars_105_en.png | 5 +++-- ....designsystem.components.avatar_Avatar_Avatars_106_en.png | 5 +++-- ....designsystem.components.avatar_Avatar_Avatars_107_en.png | 5 +++-- ....designsystem.components.avatar_Avatar_Avatars_108_en.png | 4 ++-- ....designsystem.components.avatar_Avatar_Avatars_109_en.png | 4 ++-- ....designsystem.components.avatar_Avatar_Avatars_110_en.png | 4 ++-- ....designsystem.components.avatar_Avatar_Avatars_111_en.png | 3 +++ ....designsystem.components.avatar_Avatar_Avatars_112_en.png | 3 +++ ....designsystem.components.avatar_Avatar_Avatars_113_en.png | 3 +++ 14 files changed, 37 insertions(+), 22 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_111_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_112_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_113_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png index a9623bcde8..fe88fafe4f 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:18bacb2019ed743c8cf023239b18cb438656eb523e6d0a54f692fe9d5d637270 -size 17322 +oid sha256:0075dca9fd927dc7df4e987fe5cca8d2a2ca5b268bc46916dcd49724264a3859 +size 19834 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png index 0cbaf3c23f..18a49cfc20 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl_SpaceView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9baf49cdfea6895362b19b780b4877e31b006304b1a92e47d47f941efbb773f4 -size 17165 +oid sha256:8b69241047e1d5787620331adc33f2b78084f47cf02c531a4e41011816590a09 +size 19523 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png index 9bcc262fbe..f4e93c12ae 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_102_en.png @@ -1,2 +1,3 @@ -oid sha256:8da97746633081690a09a79e3f9974257bbe0f292ad5b8ee2eed454c1273c01e -size 19747 +version https://git-lfs.github.com/spec/v1 +oid sha256:8c6688901f89d3858ec67dda889fe589fb6b59202c64a4b700c2aa484e19f4cd +size 17606 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png index 1e5c457237..53dbe79213 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_103_en.png @@ -1,2 +1,3 @@ -oid sha256:1aaa84f80b3691ed83308966e53deb8dbc97c7943d2f68a8036a6ead603ea627 -size 18270 +version https://git-lfs.github.com/spec/v1 +oid sha256:26b9908bbd388321444037dcc1aae55037d3dabc7a9f9b14c39ba871f4f9d593 +size 16128 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png index 50077c4dab..9c9b3d4717 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_104_en.png @@ -1,2 +1,3 @@ -oid sha256:ddaae721cac21a188dc3862e3e14e80eeb13c92826bccfb8364ecbd72948d9bd -size 23653 +version https://git-lfs.github.com/spec/v1 +oid sha256:1a96b6d95b8941d80035b309444b9eaa038098fb16aa84dec209fc3ee215ac9e +size 21687 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png index 47380a200a..7f55d277d5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_105_en.png @@ -1,2 +1,3 @@ -oid sha256:207d569640554b3b11cadb03a231ae0dfd85a3c470695cc8428cb2e295d98776 -size 18858 +version https://git-lfs.github.com/spec/v1 +oid sha256:8da97746633081690a09a79e3f9974257bbe0f292ad5b8ee2eed454c1273c01e +size 19747 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png index 829e43c29f..91a2bc23da 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_106_en.png @@ -1,2 +1,3 @@ -oid sha256:68ae347075a6bef936e9c905a12b6b561a01737ab886436d73f4987783a1b45f -size 17541 +version https://git-lfs.github.com/spec/v1 +oid sha256:1aaa84f80b3691ed83308966e53deb8dbc97c7943d2f68a8036a6ead603ea627 +size 18270 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png index 71fb63b1f6..a2cd42670a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_107_en.png @@ -1,2 +1,3 @@ -oid sha256:8caa1fbeb5250684363a21549cdcfff60489059c9d1f0ca115503e63675b3511 -size 22394 +version https://git-lfs.github.com/spec/v1 +oid sha256:ddaae721cac21a188dc3862e3e14e80eeb13c92826bccfb8364ecbd72948d9bd +size 23653 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_108_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_108_en.png index 7946dc4e91..885a613f50 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_108_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_108_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce1aba18ea8a6b45d9c40de9af961952e261c7c6200ab13cdfa67906d995208b -size 14888 +oid sha256:207d569640554b3b11cadb03a231ae0dfd85a3c470695cc8428cb2e295d98776 +size 18858 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_109_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_109_en.png index 0b12b366b9..4279c36d24 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_109_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_109_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a4d295ae71ba2709845312b84983b79348069ded46b30091b9fa769a587cbb7 -size 14337 +oid sha256:68ae347075a6bef936e9c905a12b6b561a01737ab886436d73f4987783a1b45f +size 17541 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_110_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_110_en.png index 556cb141b0..1ff47d58e0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_110_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_110_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da8f54591a52475c6f47fa083a1bb397e1164dd3e735562388fde4ff45644150 -size 16275 +oid sha256:8caa1fbeb5250684363a21549cdcfff60489059c9d1f0ca115503e63675b3511 +size 22394 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_111_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_111_en.png new file mode 100644 index 0000000000..7946dc4e91 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_111_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce1aba18ea8a6b45d9c40de9af961952e261c7c6200ab13cdfa67906d995208b +size 14888 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_112_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_112_en.png new file mode 100644 index 0000000000..0b12b366b9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_112_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a4d295ae71ba2709845312b84983b79348069ded46b30091b9fa769a587cbb7 +size 14337 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_113_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_113_en.png new file mode 100644 index 0000000000..556cb141b0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_Avatar_Avatars_113_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da8f54591a52475c6f47fa083a1bb397e1164dd3e735562388fde4ff45644150 +size 16275 From 0c47168b4dc07e23339b4a1182f7cba9abba80fe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 24 Sep 2025 14:30:00 +0200 Subject: [PATCH 143/145] Update dependency io.sentry:sentry-android to v8.22.0 (#5397) 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 5d604ba8f0..ea78e146b4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -206,7 +206,7 @@ haze_materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = # Analytics posthog = "com.posthog:posthog-android:3.21.2" -sentry = "io.sentry:sentry-android:8.21.1" +sentry = "io.sentry:sentry-android:8.22.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.28.0" From 5273715883b1a1c74bb59f701eab26ed9de4da67 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 24 Sep 2025 14:33:47 +0200 Subject: [PATCH 144/145] Setting version for the release 25.09.2 --- 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 14307ae741..96a308f93f 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -44,7 +44,7 @@ private const val versionMonth = 9 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 1 +private const val versionReleaseNumber = 2 object Versions { /** From db1672b8138d7311242673c9b07200d998122ed6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 24 Sep 2025 14:35:33 +0200 Subject: [PATCH 145/145] Adding fastlane file for version 25.09.2 --- fastlane/metadata/android/en-US/changelogs/202509020.txt | 2 ++ tools/release/release.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/202509020.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202509020.txt b/fastlane/metadata/android/en-US/changelogs/202509020.txt new file mode 100644 index 0000000000..8955ade680 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202509020.txt @@ -0,0 +1,2 @@ +Main changes in this version: bug fixes and improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases diff --git a/tools/release/release.sh b/tools/release/release.sh index 6727ebb309..59a29dc13c 100755 --- a/tools/release/release.sh +++ b/tools/release/release.sh @@ -146,7 +146,7 @@ printf "Creating fastlane file...\n" printf -v versionReleaseNumber2Digits "%02d" "${versionReleaseNumber}" fastlaneFile="20${versionYear}${versionMonth}${versionReleaseNumber2Digits}0.txt" fastlanePathFile="./fastlane/metadata/android/en-US/changelogs/${fastlaneFile}" -printf "Main changes in this version: TODO.\nFull changelog: https://github.com/element-hq/element-x-android/releases" > "${fastlanePathFile}" +printf "Main changes in this version: bug fixes and improvements.\nFull changelog: https://github.com/element-hq/element-x-android/releases" > "${fastlanePathFile}" read -r -p "I have created the file ${fastlanePathFile}, please edit it and press enter to continue. " git add "${fastlanePathFile}"