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 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..3ea6f9d1c9 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") @@ -42,18 +43,12 @@ 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) 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,11 +56,8 @@ 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) testImplementation(projects.services.toolbox.test) - testImplementation(libs.test.appyx.junit) - testImplementation(libs.test.arch.core) } 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..fc4fcc3a7a 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 @@ -119,7 +118,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, @@ -277,9 +275,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 } @@ -324,10 +319,6 @@ class LoggedInFlowNode( override fun onReportBugClick() { plugins().forEach { it.onOpenBugReport() } } - - override fun onLogoutForNativeSlidingSyncMigrationNeeded() { - backstack.push(NavTarget.LogoutForNativeSlidingSyncMigrationNeeded) - } } homeEntryPoint .nodeBuilder(this, buildContext) @@ -454,8 +445,7 @@ class LoggedInFlowNode( .build() } NavTarget.Ftue -> { - ftueEntryPoint.nodeBuilder(this, buildContext) - .build() + ftueEntryPoint.createNode(this, buildContext) } NavTarget.RoomDirectorySearch -> { roomDirectoryEntryPoint.nodeBuilder(this, buildContext) @@ -486,17 +476,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/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt index 818e670e46..3f1d40335d 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 @@ -47,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 @@ -65,13 +64,12 @@ 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, private val presenter: RootPresenter, private val bugReportEntryPoint: BugReportEntryPoint, - private val viewFolderEntryPoint: ViewFolderEntryPoint, private val signedOutEntryPoint: SignedOutEntryPoint, private val intentResolver: IntentResolver, private val oidcActionFlow: OidcActionFlow, @@ -154,7 +152,7 @@ class RootFlowNode( onSuccess: (SessionId) -> Unit, onFailure: () -> Unit ) { - val latestSessionId = authenticationService.getLatestSessionId() + val latestSessionId = sessionStore.getLatestSessionId() if (latestSessionId == null) { onFailure() return @@ -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() } @@ -294,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())) { @@ -311,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) @@ -368,3 +342,5 @@ class RootFlowNode( .attachSession() } } + +private suspend fun SessionStore.getLatestSessionId() = getLatestSession()?.userId?.let(::SessionId) 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/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/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/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/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/analytics/impl/build.gradle.kts b/features/analytics/impl/build.gradle.kts index b722196c59..ddf093d9c3 100644 --- a/features/analytics/impl/build.gradle.kts +++ b/features/analytics/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright 2023, 2024 New Vector Ltd. @@ -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..b5ec819632 --- /dev/null +++ b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/DefaultAnalyticsEntryPointTest.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.analytics.impl + +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 + +class DefaultAnalyticsEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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) + } +} 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/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/build.gradle.kts b/features/call/impl/build.gradle.kts index 0c9ae5a4b0..9efe5ba75b 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,5 @@ 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) + testImplementation(projects.services.toolbox.test) } 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..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,4 +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/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 54a5e567c8..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 @@ -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 @@ -53,7 +54,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. @@ -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 @@ -118,8 +120,20 @@ class DefaultActiveCallManager( override suspend fun registerIncomingCall(notificationData: CallNotificationData) { mutex.withLock { + val ringDuration = + min( + notificationData.expirationTimestamp - systemClock.epochMillis(), + 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(ms): $ringDuration") if (activeCall.value != null) { displayMissedCallNotification(notificationData) Timber.tag(tag).w("Already have an active call, ignoring incoming call: $notificationData") @@ -138,14 +152,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) } } } @@ -180,12 +194,22 @@ 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 (currentActiveCall.callState is CallState.Ringing) { + // Decline the call + val notificationData = currentActiveCall.callState.notificationData + matrixClientProvider.getOrRestore(notificationData.sessionId).getOrNull() + ?.getRoom(notificationData.roomId) + ?.declineCall(notificationData.eventId) + } cancelIncomingCallNotification() if (activeWakeLock?.isHeld == true) { @@ -226,6 +250,7 @@ class DefaultActiveCallManager( notificationChannelId = notificationData.notificationChannelId, timestamp = notificationData.timestamp, textContent = notificationData.textContent, + expirationTimestamp = notificationData.expirationTimestamp, ) ?: return runCatchingExceptions { notificationManagerCompat.notify( @@ -256,6 +281,43 @@ 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 session 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 ringing 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 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 call declined from another session") + 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/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/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 84084c38fe..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 @@ -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 @@ -36,8 +39,12 @@ 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 +import io.mockk.coVerify import io.mockk.mockk import io.mockk.verify import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -164,6 +171,102 @@ 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 { + plantTestTimber() + 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() @@ -267,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) @@ -277,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, @@ -292,5 +473,6 @@ class DefaultActiveCallManagerTest { defaultCurrentCallService = DefaultCurrentCallService(), appForegroundStateService = FakeAppForegroundStateService(), imageLoaderHolder = FakeImageLoaderHolder(), + systemClock = systemClock, ) } 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..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,6 +30,7 @@ fun aCallNotificationData( avatarUrl: String? = AN_AVATAR_URL, notificationChannelId: String = "channel_id", timestamp: Long = 0L, + expirationTimestamp: Long = 30_000L, 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/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/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/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..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 @@ -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( ) } } + +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/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/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 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)) + } +} 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/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/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..61c7c052c5 --- /dev/null +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.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.createroom.impl + +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 + +class DefaultCreateRoomEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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/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/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/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..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,10 +148,10 @@ class AccountDeactivationPresenterTest { assertThat(finalState2.accountDeactivationAction).isEqualTo(AsyncAction.Uninitialized) } } - - 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..05ad52efe9 --- /dev/null +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.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.logout.impl + +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 + +class DefaultAccountDeactivationEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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/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/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/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 new file mode 100644 index 0000000000..50cc2eadce --- /dev/null +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.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.ftue.impl + +import android.content.Context +import android.content.Intent +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 + +class DefaultFtueEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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.createNode(parentNode, BuildContext.root(null)) + 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/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() } } 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/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) 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/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..7d0c95befd --- /dev/null +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.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.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() + } + 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/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/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/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/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..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 @@ -11,11 +11,11 @@ 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 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 @@ -148,28 +148,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..7cdf208b9a --- /dev/null +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.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.invite.impl.declineandblock + +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 + +class DefaultDeclineAndBlockEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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/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/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/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/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 c8a107eba4..e8e891397c 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 @@ -76,7 +76,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/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/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..af75fd528c --- /dev/null +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.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.joinroom.impl + +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 +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.Rule +import org.junit.Test +import java.util.Optional + +class DefaultJoinRoomEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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 6deb39fba4..d636e9fb34 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 @@ -1034,39 +1034,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, @@ -1087,3 +1054,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/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/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..b6b6d766c7 --- /dev/null +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt @@ -0,0 +1,36 @@ +/* + * 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.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 + +class DefaultKnockRequestsListEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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/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/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/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 new file mode 100644 index 0000000000..3209e28fe6 --- /dev/null +++ b/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.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.licenses.impl + +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 + +class DefaultOpenSourcesLicensesEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @Test + fun `test node builder`() { + val entryPoint = DefaultOpenSourcesLicensesEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + DependenciesFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val result = entryPoint.createNode(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(DependenciesFlowNode::class.java) + } +} 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/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..9be79c7092 --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.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.location.impl.send + +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 +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.Rule +import org.junit.Test + +class DefaultSendLocationEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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..d31ef0c0e4 --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.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.features.location.impl.show + +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 +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.Rule +import org.junit.Test + +class DefaultShowLocationEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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/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/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 new file mode 100644 index 0000000000..822d275063 --- /dev/null +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt @@ -0,0 +1,68 @@ +/* + * 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.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.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule +import org.junit.Test + +class DefaultLockScreenEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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/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/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/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..c10d22c51a --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.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.login.impl + +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 +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.Rule +import org.junit.Test + +class DefaultLoginEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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/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/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/build.gradle.kts b/features/logout/impl/build.gradle.kts index 09fdc1bd96..215c273913 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,8 @@ 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) + 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/DefaultLogoutEntryPointTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt new file mode 100644 index 0000000000..01d1bfc6ca --- /dev/null +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.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.logout.impl + +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 + +class DefaultLogoutEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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/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/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) } } 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/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) } 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/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/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/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/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..a4753807cd --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt @@ -0,0 +1,136 @@ +/* + * 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.arch.core.executor.testing.InstantTaskExecutorRule +import androidx.compose.runtime.Composable +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 +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.Rule +import org.junit.Test + +class DefaultMessagesEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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, + expirationTimestamp: 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) + } + + @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/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/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/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/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/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/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/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..bf77cb4535 --- /dev/null +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.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.poll.impl.create + +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 +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.Rule +import org.junit.Test + +class DefaultCreatePollEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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..dfab33e837 --- /dev/null +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.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.poll.impl.history + +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 + +class DefaultPollHistoryEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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/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/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/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/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..807ff3a5c6 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.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.features.preferences.impl + +import android.content.Context +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 +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.Rule +import org.junit.Test + +class DefaultPreferencesEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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 createNode(parentNode: 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) + } + + @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/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 ea4eb33ba6..b17d78f3aa 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. @@ -27,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) @@ -45,19 +47,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/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/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..23d74f7247 --- /dev/null +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.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.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 +import org.junit.Rule +import org.junit.Test + +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 -> + BugReportFlowNode( + buildContext = buildContext, + plugins = plugins, + viewFolderEntryPoint = object : ViewFolderEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + ) + } + val callback = object : BugReportEntryPoint.Callback { + override fun onDone() = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(BugReportFlowNode::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/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/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..c9f850062e --- /dev/null +++ b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.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.reportroom.impl + +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 + +class DefaultReportRoomEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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/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..238b35017b --- /dev/null +++ b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.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.roomaliasresolver.impl + +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 +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 + +class DefaultRoomAliasResolverEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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/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/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/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/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) { 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/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/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..f2412e616b --- /dev/null +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt @@ -0,0 +1,123 @@ +/* + * 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.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 +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.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 +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 + +class DefaultRoomDetailsEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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, + expirationTimestamp: 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) + } + + @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)) + } +} 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/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..d544f55000 --- /dev/null +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.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.roomdirectory.impl + +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 +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.Rule +import org.junit.Test + +class DefaultRoomDirectoryEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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/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/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/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..7741b5141a --- /dev/null +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt @@ -0,0 +1,48 @@ +/* + * 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.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 + +class DefaultSecureBackupEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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/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/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..66ee853d26 --- /dev/null +++ b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt @@ -0,0 +1,61 @@ +/* + * 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.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 +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 + +class DefaultShareEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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/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/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..860ad88d8a --- /dev/null +++ b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.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.signedout.impl + +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 + +class DefaultSignedOutEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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..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 @@ -26,8 +27,6 @@ class SignedOutPresenterTest { @get:Rule val warmUpRule = WarmUpRule() - private val appName = "AppName" - @Test fun `present - initial state`() = runTest { val aSessionData = aSessionData() @@ -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) } } @@ -64,15 +63,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 = AN_APPLICATION_NAME), + ) } 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/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/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) 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 3b07e06051..1955ab652e 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 @@ -39,7 +39,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..465fde3425 --- /dev/null +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt @@ -0,0 +1,64 @@ +/* + * 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.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 +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.Rule +import org.junit.Test + +class DefaultSpaceEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @Test + fun `test node builder`() { + 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/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/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..8f4a41a3fa --- /dev/null +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt @@ -0,0 +1,52 @@ +/* + * 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.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 + +class DefaultStartChatEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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/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/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..1537167d20 --- /dev/null +++ b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt @@ -0,0 +1,86 @@ +/* + * 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.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 +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.Rule +import org.junit.Test + +class DefaultUserProfileEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @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, + expirationTimestamp: 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/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/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/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/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/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/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..ad586fc7fb --- /dev/null +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt @@ -0,0 +1,48 @@ +/* + * 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.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 + +class DefaultIncomingVerificationEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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..52ff36dbd6 --- /dev/null +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.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.verifysession.impl.outgoing + +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 + +class DefaultOutgoingVerificationEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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/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, 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..47d5992d8c --- /dev/null +++ b/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.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.viewfolder.impl + +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.ViewFolderFlowNode +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Rule +import org.junit.Test + +class DefaultViewFolderEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @Test + fun `test node builder`() { + val entryPoint = DefaultViewFolderEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ViewFolderFlowNode( + 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(ViewFolderFlowNode::class.java) + assertThat(result.plugins).contains(ViewFolderFlowNode.Inputs(params.rootPath)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0825c5049e..eca610ae30 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,9 +17,9 @@ 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" +camera = "1.5.0" # Compose compose_bom = "2025.07.00" @@ -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 @@ -152,14 +152,22 @@ 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_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.18" +test_truth = "com.google.truth:truth:1.4.5" +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" 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.18" + # 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,14 +184,13 @@ 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_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" } 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" } @@ -198,8 +205,8 @@ 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" -sentry = "io.sentry:sentry-android:8.21.0" +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" 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/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/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/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..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() @@ -46,8 +37,7 @@ inline fun NodeFactoriesBindings.createNode( return node as N } -// @BindingContainer -interface NodeFactoriesBindings { +fun interface NodeFactoriesBindings { @Multibinds fun nodeFactories(): Map, AssistedNodeFactory<*>> } 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/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/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/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/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/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/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/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/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/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..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 @@ -13,14 +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? - /** * Restore a session from a [sessionId]. * Do not restore anything it the access token is not valid anymore. 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/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..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,10 @@ 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 data object CallHangup : MessageLike @@ -118,7 +119,7 @@ sealed interface NotificationContent { ) : NotificationContent } -enum class CallNotifyType { +enum class RtcNotificationType { RING, NOTIFY } 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/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/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/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/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/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 } 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/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/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..956e645571 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) } @@ -689,12 +688,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/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..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 @@ -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,14 +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) } - } - override suspend fun restoreSession(sessionId: SessionId): Result = withContext(coroutineDispatchers.io) { runCatchingExceptions { val sessionData = sessionStore.getSession(sessionId.value) @@ -158,7 +148,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 +172,7 @@ class RustMatrixAuthenticationService( sessionPaths = currentSessionPaths, ) clear() - sessionStore.storeData(sessionData) + sessionStore.addSession(sessionData) SessionId(sessionData.userId) } } @@ -250,7 +240,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 +285,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/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..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.CallNotifyType 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.NotifyType 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 { @@ -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.RtcNotification( + 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 SdkRtcNotificationType.map(): RtcNotificationType = when (this) { + SdkRtcNotificationType.NOTIFICATION -> RtcNotificationType.NOTIFY + SdkRtcNotificationType.RING -> RtcNotificationType.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..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.CALL_NOTIFY + 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.CALL_NOTIFY -> 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/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..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 @@ -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.value) + } + } + + override suspend fun subscribeToCallDecline(notificationEventId: EventId): Flow = withContext(roomDispatcher) { + mxCallbackFlow { + 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) } } 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/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/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/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..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,10 +18,10 @@ 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.VirtualElementCallWidgetOptions +import uniffi.matrix_sdk.VirtualElementCallWidgetConfig +import uniffi.matrix_sdk.VirtualElementCallWidgetProperties import uniffi.matrix_sdk.Intent as CallIntent @ContributesBinding(AppScope::class) @@ -31,19 +31,14 @@ 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 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 +46,25 @@ class DefaultCallWidgetSettingsProvider( sentryDsn = callAnalyticsCredentialsProvider.sentryDsn.takeIf { isAnalyticsEnabled }, sentryEnvironment = if (buildMeta.buildType == BuildType.RELEASE) "RELEASE" else "DEBUG", parentUrl = null, - // For backwards compatibility, it'll be ignored in recent versions of Element Call - hideHeader = true, - controlledMediaDevices = true, - header = HeaderStyle.APP_BAR, - sendNotificationType = if (direct) NotificationType.RING else NotificationType.NOTIFICATION, ) - val rustWidgetSettings = newVirtualElementCallWidget(options) + val config = VirtualElementCallWidgetConfig( + // 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, + config = config, + ) return MatrixWidgetSettings.fromRustWidgetSettings(rustWidgetSettings) } } 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/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/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/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() } 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/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/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, + ) + } +} 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() } 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") 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..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 @@ -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") @@ -44,14 +41,6 @@ class FakeMatrixAuthenticationService( private var matrixClient: MatrixClient? = null private var onAuthenticationListener: ((MatrixClient) -> Unit)? = null - 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 { matrixClientResult?.let { return it.invoke(sessionId) 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) { 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/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 ca424eac11..3579f162b9 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 @@ -23,11 +23,11 @@ class FakeSpaceRoomList( initialSpaceRoomList: SpaceRoomList.PaginationStatus = SpaceRoomList.PaginationStatus.Loading, private val paginateResult: () -> Result = { lambdaError() }, ) : SpaceRoomList { - private val _currentSpaceFlow: MutableStateFlow> = MutableStateFlow(Optional.ofNullable(initialSpaceFlowValue)) - override fun currentSpaceFlow() = _currentSpaceFlow.asStateFlow() + private val currentSpaceMutableStateFlow: MutableStateFlow> = MutableStateFlow(Optional.ofNullable(initialSpaceFlowValue)) + override fun currentSpaceFlow(): StateFlow> = currentSpaceMutableStateFlow.asStateFlow() fun emitCurrentSpace(value: SpaceRoom?) { - _currentSpaceFlow.value = Optional.ofNullable(value) + currentSpaceMutableStateFlow.value = Optional.ofNullable(value) } private val _spaceRoomsFlow: MutableStateFlow> = MutableStateFlow(initialSpaceRoomsValue) 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) } } 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..4af1c54f46 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,12 @@ dependencies { implementation(projects.libraries.di) 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) 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/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/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/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) 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() } } } 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..0f8b0fedfb --- /dev/null +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.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.libraries.mediaviewer.impl + +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 +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +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 +import org.junit.Test + +class DefaultMediaGalleryEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @Test + fun `test node builder`() { + val entryPoint = DefaultMediaGalleryEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + MediaGalleryFlowNode( + 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(MediaGalleryFlowNode::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..3af2e8cf69 --- /dev/null +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt @@ -0,0 +1,147 @@ +/* + * 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.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 +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.Rule +import org.junit.Test + +class DefaultMediaViewerEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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 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/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/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, 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/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..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.CallNotifyType 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 @@ -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,9 +104,10 @@ 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, ) } 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/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/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..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,6 +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/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..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 } @@ -296,6 +277,7 @@ class DefaultPushHandler( senderName = notifiableEvent.senderDisambiguatedDisplayName, avatarUrl = notifiableEvent.roomAvatarUrl, timestamp = notifiableEvent.timestamp, + expirationTimestamp = notifiableEvent.expirationTimestamp, notificationChannelId = notificationChannels.getChannelForIncomingCall(ring = true), textContent = notifiableEvent.description, ) 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/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..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 @@ -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.CallNotifyType 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 @@ -61,11 +61,12 @@ class DefaultCallNotificationEventResolverTest { isUpdated = false, senderDisambiguatedDisplayName = A_USER_NAME_2, senderAvatarUrl = null, - callNotifyType = CallNotifyType.RING, + expirationTimestamp = 1567L, + rtcNotificationType = RtcNotificationType.RING, ) val notificationData = aNotificationData( - content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.RING) + content = NotificationContent.MessageLike.RtcNotification(A_USER_ID_2, RtcNotificationType.RING, 1567) ) val result = resolver.resolveEvent(A_SESSION_ID, notificationData) assertThat(result.getOrNull()).isEqualTo(expectedResult) @@ -105,11 +106,11 @@ class DefaultCallNotificationEventResolverTest { imageUriString = null, imageMimeType = null, threadId = null, - type = "m.call.notify", + type = "org.matrix.msc4075.rtc.notification", ) val notificationData = aNotificationData( - content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.NOTIFY) + content = NotificationContent.MessageLike.RtcNotification(A_USER_ID_2, RtcNotificationType.NOTIFY, 0) ) val result = resolver.resolveEvent(A_SESSION_ID, notificationData) assertThat(result.getOrNull()).isEqualTo(expectedResult) @@ -149,11 +150,11 @@ class DefaultCallNotificationEventResolverTest { imageUriString = null, imageMimeType = null, threadId = null, - type = "m.call.notify", + type = "org.matrix.msc4075.rtc.notification", ) val notificationData = aNotificationData( - content = NotificationContent.MessageLike.CallNotify(A_USER_ID_2, CallNotifyType.RING) + 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 2d99e31d74..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.CallNotifyType 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 @@ -693,9 +693,10 @@ 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 ), )) ) @@ -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..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,8 +119,9 @@ 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( sessionId = sessionId, eventId = eventId, @@ -129,6 +130,7 @@ fun aNotifiableCallEvent( editedEventId = null, description = "description", timestamp = timestamp, + expirationTimestamp = expirationTimestamp, canBeReplaced = false, isRedacted = false, isUpdated = false, @@ -136,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 a070156d05..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,13 +14,12 @@ 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 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 @@ -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, ) @@ -388,7 +334,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()) ) ) ) @@ -440,7 +386,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( @@ -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/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/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() 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/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..bb9c15e7e6 --- /dev/null +++ b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.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.libraries.roomselect.impl + +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 +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.Rule +import org.junit.Test + +class DefaultRoomSelectEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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/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..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,9 +11,9 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map interface SessionStore { - fun isLoggedIn(): Flow + fun loggedInStateFlow(): 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/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/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..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) @@ -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..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 @@ -44,22 +44,24 @@ 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) } @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/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..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 @@ -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) 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/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..d9bf607531 --- /dev/null +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.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.troubleshoot.impl + +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 + +class DefaultNotificationTroubleShootEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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..3604622f5c --- /dev/null +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.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.troubleshoot.impl.history + +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 +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.Rule +import org.junit.Test + +class DefaultPushHistoryEntryPointTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @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) + } +} 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 c7694387a6..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" @@ -304,6 +306,7 @@ Reason: %1$s." "Sent" ". " "Server not supported" + "Server unreachable" "Server URL" "Settings" "Shared location" @@ -409,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/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/Versions.kt b/plugins/src/main/kotlin/Versions.kt index f02b468b6e..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,27 +28,80 @@ 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 do not forget to update the value for `buildToolsVersion` - // in the file `tools/release/release.sh` + /** + * 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 - // When updating the `minSdk`, make sure to update the value of `minSdkVersion` in the file `tools/release/release.sh` + /** + * 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) + + // 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" } + } } diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index 440f9d338b..2b6c531eda 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -19,6 +19,8 @@ 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) +private fun DependencyHandlerScope.testReleaseImplementation(dependency: Any) = dependencies.add("testReleaseImplementation", dependency) internal fun DependencyHandler.implementation(dependency: Any) = add("implementation", dependency) // Implementation + config block @@ -32,6 +34,30 @@ 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, + includeTestComposeView: Boolean = false, +) { + 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) + 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) + } +} + /** * Dependencies used by all the modules */ 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,], 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/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() 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/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") + } + }) +} 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..79def028f7 --- /dev/null +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/node/TestParentNode.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.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) + } + } +} 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.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.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.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.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.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/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.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 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 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 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) } 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 {