From 5a192b49d702266e8e431ad9a0b158e1a5c913a7 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 4 Apr 2024 20:36:16 +0200 Subject: [PATCH 01/52] Room navigation : add a JoinedRoomFlowNode so we use RoomFlowNode for managing different routes --- .../android/appnav/LoggedInFlowNode.kt | 15 +- .../android/appnav/room/RoomFlowNode.kt | 102 +++++++------ .../appnav/room/RoomNavigationTarget.kt | 23 +++ .../appnav/room/joined/JoinedRoomFlowNode.kt | 138 ++++++++++++++++++ .../JoinedRoomLoadedFlowNode.kt} | 27 ++-- .../room/{ => joined}/LoadingRoomNodeView.kt | 4 +- .../room/{ => joined}/LoadingRoomState.kt | 4 +- .../android/appnav/RoomFlowNodeTest.kt | 18 +-- .../room/LoadingRoomStateFlowFactoryTest.kt | 2 + .../matrix/api/roomlist/RoomListService.kt | 15 ++ .../impl/roomlist/RustRoomListService.kt | 28 ++++ 11 files changed, 298 insertions(+), 78 deletions(-) create mode 100644 appnav/src/main/kotlin/io/element/android/appnav/room/RoomNavigationTarget.kt create mode 100644 appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomFlowNode.kt rename appnav/src/main/kotlin/io/element/android/appnav/room/{RoomLoadedFlowNode.kt => joined/JoinedRoomLoadedFlowNode.kt} (90%) rename appnav/src/main/kotlin/io/element/android/appnav/room/{ => joined}/LoadingRoomNodeView.kt (97%) rename appnav/src/main/kotlin/io/element/android/appnav/room/{ => joined}/LoadingRoomState.kt (96%) 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 2027f2868a..8ff7ecfaa8 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -42,7 +42,8 @@ import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.appnav.loggedin.LoggedInNode import io.element.android.appnav.room.RoomFlowNode -import io.element.android.appnav.room.RoomLoadedFlowNode +import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode +import io.element.android.appnav.room.RoomNavigationTarget import io.element.android.features.createroom.api.CreateRoomEntryPoint import io.element.android.features.ftue.api.FtueEntryPoint import io.element.android.features.ftue.api.state.FtueService @@ -213,7 +214,7 @@ class LoggedInFlowNode @AssistedInject constructor( @Parcelize data class Room( val roomId: RoomId, - val initialElement: RoomLoadedFlowNode.NavTarget = RoomLoadedFlowNode.NavTarget.Messages + val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages ) : NavTarget @Parcelize @@ -273,7 +274,7 @@ class LoggedInFlowNode @AssistedInject constructor( } override fun onRoomSettingsClicked(roomId: RoomId) { - backstack.push(NavTarget.Room(roomId, initialElement = RoomLoadedFlowNode.NavTarget.RoomDetails)) + backstack.push(NavTarget.Room(roomId, initialElement = RoomNavigationTarget.Details)) } override fun onReportBugClicked() { @@ -290,7 +291,7 @@ class LoggedInFlowNode @AssistedInject constructor( .build() } is NavTarget.Room -> { - val callback = object : RoomLoadedFlowNode.Callback { + val callback = object : JoinedRoomLoadedFlowNode.Callback { override fun onOpenRoom(roomId: RoomId) { backstack.push(NavTarget.Room(roomId)) } @@ -317,7 +318,7 @@ class LoggedInFlowNode @AssistedInject constructor( } override fun onOpenRoomNotificationSettings(roomId: RoomId) { - backstack.push(NavTarget.Room(roomId, initialElement = RoomLoadedFlowNode.NavTarget.RoomNotificationSettings)) + backstack.push(NavTarget.Room(roomId, initialElement = RoomNavigationTarget.NotificationSettings)) } } val inputs = PreferencesEntryPoint.Params(navTarget.initialElement) @@ -349,6 +350,10 @@ class LoggedInFlowNode @AssistedInject constructor( backstack.pop() } + override fun onInviteClicked(roomId: RoomId) { + backstack.push(NavTarget.Room(roomId)) + } + override fun onInviteAccepted(roomId: RoomId) { backstack.push(NavTarget.Room(roomId)) } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt index b45207b034..dd53d6168b 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,13 @@ * limitations under the License. */ -@file:OptIn(ExperimentalMaterial3Api::class) - package io.element.android.appnav.room import android.os.Parcelable -import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.lifecycle.lifecycleScope import com.bumble.appyx.core.modality.BuildContext @@ -36,26 +34,36 @@ import com.bumble.appyx.navmodel.backstack.operation.newRoot import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode +import io.element.android.appnav.room.joined.JoinedRoomFlowNode +import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode import io.element.android.features.networkmonitor.api.NetworkMonitor -import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.libraries.architecture.BackstackView import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator +import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.core.RoomId -import kotlinx.coroutines.flow.distinctUntilChanged +import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.room.RoomMembershipObserver +import io.element.android.libraries.matrix.api.roomlist.RoomListService +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize +import timber.log.Timber +import kotlin.jvm.optionals.getOrNull @ContributesNode(SessionScope::class) class RoomFlowNode @AssistedInject constructor( @Assisted val buildContext: BuildContext, @Assisted plugins: List, - loadingRoomStateFlowFactory: LoadingRoomStateFlowFactory, + private val roomListService: RoomListService, + private val roomMembershipObserver: RoomMembershipObserver, private val networkMonitor: NetworkMonitor, ) : BaseFlowNode( @@ -68,64 +76,70 @@ class RoomFlowNode @AssistedInject constructor( ) { data class Inputs( val roomId: RoomId, - val initialElement: RoomLoadedFlowNode.NavTarget = RoomLoadedFlowNode.NavTarget.Messages, + val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages, ) : NodeInputs private val inputs: Inputs = inputs() - private val loadingRoomStateStateFlow = loadingRoomStateFlowFactory.create(lifecycleScope, inputs.roomId) sealed interface NavTarget : Parcelable { @Parcelize data object Loading : NavTarget @Parcelize - data object Loaded : NavTarget + data object JoinRoom : NavTarget + + @Parcelize + data object JoinedRoom : NavTarget } override fun onBuilt() { super.onBuilt() - loadingRoomStateStateFlow - .map { - it is LoadingRoomState.Loaded - } - .distinctUntilChanged() - .onEach { isLoaded -> - if (isLoaded) { - backstack.newRoot(NavTarget.Loaded) - } else { - backstack.newRoot(NavTarget.Loading) + roomListService.getUserMembershipForRoom( + inputs.roomId + ).onEach { membership -> + Timber.d("RoomMembership = $membership") + when { + membership.getOrNull() == CurrentUserMembership.JOINED -> { + backstack.newRoot(NavTarget.JoinedRoom) } + else -> { + backstack.newRoot(NavTarget.JoinRoom) + } + } + } + .flowOn(Dispatchers.Default) + .launchIn(lifecycleScope) + + roomMembershipObserver.updates + .filter { update -> update.roomId == inputs.roomId && !update.isUserInRoom } + .onEach { + navigateUp() } .launchIn(lifecycleScope) } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { - NavTarget.Loaded -> { - val roomFlowNodeCallback = plugins() - val awaitRoomState = loadingRoomStateStateFlow.value - if (awaitRoomState is LoadingRoomState.Loaded) { - val inputs = RoomLoadedFlowNode.Inputs(awaitRoomState.room, initialElement = inputs.initialElement) - createNode(buildContext, plugins = listOf(inputs) + roomFlowNodeCallback) - } else { - loadingNode(buildContext, this::navigateUp) - } - } - NavTarget.Loading -> { - loadingNode(buildContext, this::navigateUp) + NavTarget.Loading -> loadingNode(buildContext) + NavTarget.JoinRoom -> joinRoomNode(buildContext) + NavTarget.JoinedRoom -> { + val roomFlowNodeCallback = plugins() + val inputs = JoinedRoomFlowNode.Inputs(inputs.roomId, initialElement = inputs.initialElement) + createNode(buildContext, plugins = listOf(inputs) + roomFlowNodeCallback) } } } - private fun loadingNode(buildContext: BuildContext, onBackClicked: () -> Unit) = node(buildContext) { modifier -> - val loadingRoomState by loadingRoomStateStateFlow.collectAsState() - val networkStatus by networkMonitor.connectivity.collectAsState() - LoadingRoomNodeView( - state = loadingRoomState, - hasNetworkConnection = networkStatus == NetworkStatus.Online, - modifier = modifier, - onBackClicked = onBackClicked - ) + private fun loadingNode(buildContext: BuildContext) = node(buildContext) { + Box(modifier = it.fillMaxSize(), contentAlignment = Alignment.Center) { + CircularProgressIndicator() + } + } + + private fun joinRoomNode(buildContext: BuildContext) = node(buildContext) { + Box(modifier = it.fillMaxSize(), contentAlignment = Alignment.Center) { + Text("Unknown Room") + } } @Composable diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomNavigationTarget.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomNavigationTarget.kt new file mode 100644 index 0000000000..901b2667be --- /dev/null +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomNavigationTarget.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.appnav.room + +enum class RoomNavigationTarget { + Messages, + Details, + NotificationSettings, +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomFlowNode.kt new file mode 100644 index 0000000000..36def888ac --- /dev/null +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomFlowNode.kt @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(ExperimentalMaterial3Api::class) + +package io.element.android.appnav.room.joined + +import android.os.Parcelable +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.lifecycleScope +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.navigation.transition.JumpToEndTransitionHandler +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 +import com.bumble.appyx.navmodel.backstack.operation.newRoot +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.appnav.room.RoomNavigationTarget +import io.element.android.features.networkmonitor.api.NetworkMonitor +import io.element.android.features.networkmonitor.api.NetworkStatus +import io.element.android.libraries.architecture.BackstackView +import io.element.android.libraries.architecture.BaseFlowNode +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.RoomId +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.parcelize.Parcelize + +@ContributesNode(SessionScope::class) +class JoinedRoomFlowNode @AssistedInject constructor( + @Assisted val buildContext: BuildContext, + @Assisted plugins: List, + loadingRoomStateFlowFactory: LoadingRoomStateFlowFactory, + private val networkMonitor: NetworkMonitor, +) : + BaseFlowNode( + backstack = BackStack( + initialElement = NavTarget.Loading, + savedStateMap = buildContext.savedStateMap, + ), + buildContext = buildContext, + plugins = plugins + ) { + data class Inputs( + val roomId: RoomId, + val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages, + ) : NodeInputs + + private val inputs: Inputs = inputs() + private val loadingRoomStateStateFlow = loadingRoomStateFlowFactory.create(lifecycleScope, inputs.roomId) + + sealed interface NavTarget : Parcelable { + @Parcelize + data object Loading : NavTarget + + @Parcelize + data object Loaded : NavTarget + } + + override fun onBuilt() { + super.onBuilt() + loadingRoomStateStateFlow + .map { + it is LoadingRoomState.Loaded + } + .distinctUntilChanged() + .onEach { isLoaded -> + if (isLoaded) { + backstack.newRoot(NavTarget.Loaded) + } else { + backstack.newRoot(NavTarget.Loading) + } + } + .launchIn(lifecycleScope) + } + + override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { + return when (navTarget) { + NavTarget.Loaded -> { + val roomFlowNodeCallback = plugins() + val awaitRoomState = loadingRoomStateStateFlow.value + if (awaitRoomState is LoadingRoomState.Loaded) { + val inputs = JoinedRoomLoadedFlowNode.Inputs(awaitRoomState.room, initialElement = inputs.initialElement) + createNode(buildContext, plugins = listOf(inputs) + roomFlowNodeCallback) + } else { + loadingNode(buildContext, this::navigateUp) + } + } + NavTarget.Loading -> { + loadingNode(buildContext, this::navigateUp) + } + } + } + + private fun loadingNode(buildContext: BuildContext, onBackClicked: () -> Unit) = node(buildContext) { modifier -> + val loadingRoomState by loadingRoomStateStateFlow.collectAsState() + val networkStatus by networkMonitor.connectivity.collectAsState() + LoadingRoomNodeView( + state = loadingRoomState, + hasNetworkConnection = networkStatus == NetworkStatus.Online, + modifier = modifier, + onBackClicked = onBackClicked + ) + } + + @Composable + override fun View(modifier: Modifier) { + BackstackView( + transitionHandler = JumpToEndTransitionHandler(), + ) + } +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomLoadedFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt similarity index 90% rename from appnav/src/main/kotlin/io/element/android/appnav/room/RoomLoadedFlowNode.kt rename to appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt index 21e412ef63..ade1f7e147 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomLoadedFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.appnav.room +package io.element.android.appnav.room.joined import android.os.Parcelable import androidx.compose.runtime.Composable @@ -32,6 +32,7 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.appnav.di.RoomComponentFactory +import io.element.android.appnav.room.RoomNavigationTarget import io.element.android.features.messages.api.MessagesEntryPoint import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint import io.element.android.libraries.architecture.BackstackView @@ -46,15 +47,12 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.services.appnavstate.api.AppNavigationStateService import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize import timber.log.Timber @ContributesNode(SessionScope::class) -class RoomLoadedFlowNode @AssistedInject constructor( +class JoinedRoomLoadedFlowNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, private val messagesEntryPoint: MessagesEntryPoint, @@ -63,9 +61,13 @@ class RoomLoadedFlowNode @AssistedInject constructor( private val appCoroutineScope: CoroutineScope, roomComponentFactory: RoomComponentFactory, roomMembershipObserver: RoomMembershipObserver, -) : BaseFlowNode( +) : BaseFlowNode( backstack = BackStack( - initialElement = plugins.filterIsInstance(Inputs::class.java).first().initialElement, + initialElement = when(plugins.filterIsInstance(Inputs::class.java).first().initialElement){ + RoomNavigationTarget.Messages -> NavTarget.Messages + RoomNavigationTarget.Details -> NavTarget.RoomDetails + RoomNavigationTarget.NotificationSettings -> NavTarget.RoomNotificationSettings + }, savedStateMap = buildContext.savedStateMap, ), buildContext = buildContext, @@ -79,7 +81,7 @@ class RoomLoadedFlowNode @AssistedInject constructor( data class Inputs( val room: MatrixRoom, - val initialElement: NavTarget = NavTarget.Messages, + val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages, ) : NodeInputs private val inputs: Inputs = inputs() @@ -108,13 +110,6 @@ class RoomLoadedFlowNode @AssistedInject constructor( appNavigationStateService.onLeavingRoom(id) } ) - roomMembershipObserver.updates - .filter { update -> update.roomId == inputs.room.roomId && !update.isUserInRoom } - .onEach { - navigateUp() - } - .launchIn(lifecycleScope) - inputs() } private fun fetchRoomMembers() = lifecycleScope.launch { diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/LoadingRoomNodeView.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/LoadingRoomNodeView.kt similarity index 97% rename from appnav/src/main/kotlin/io/element/android/appnav/room/LoadingRoomNodeView.kt rename to appnav/src/main/kotlin/io/element/android/appnav/room/joined/LoadingRoomNodeView.kt index 8db8d608b2..14fb955cb5 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/LoadingRoomNodeView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/LoadingRoomNodeView.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.appnav.room +package io.element.android.appnav.room.joined import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/LoadingRoomState.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/LoadingRoomState.kt similarity index 96% rename from appnav/src/main/kotlin/io/element/android/appnav/room/LoadingRoomState.kt rename to appnav/src/main/kotlin/io/element/android/appnav/room/joined/LoadingRoomState.kt index 0798979812..dbc190354f 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/LoadingRoomState.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/LoadingRoomState.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.appnav.room +package io.element.android.appnav.room.joined import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.di.SessionScope diff --git a/appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt index ecc6a5dad0..5d5c66b32b 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt @@ -27,7 +27,7 @@ import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.bumble.appyx.testing.unit.common.helper.parentNodeTestHelper import com.google.common.truth.Truth.assertThat import io.element.android.appnav.di.RoomComponentFactory -import io.element.android.appnav.room.RoomLoadedFlowNode +import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode import io.element.android.features.messages.api.MessagesEntryPoint import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint import io.element.android.libraries.architecture.childNode @@ -92,7 +92,7 @@ class RoomFlowNodeTest { messagesEntryPoint: MessagesEntryPoint = FakeMessagesEntryPoint(), roomDetailsEntryPoint: RoomDetailsEntryPoint = FakeRoomDetailsEntryPoint(), coroutineScope: CoroutineScope, - ) = RoomLoadedFlowNode( + ) = JoinedRoomLoadedFlowNode( buildContext = BuildContext.root(savedStateMap = null), plugins = plugins, messagesEntryPoint = messagesEntryPoint, @@ -108,7 +108,7 @@ class RoomFlowNodeTest { // GIVEN val room = FakeMatrixRoom() val fakeMessagesEntryPoint = FakeMessagesEntryPoint() - val inputs = RoomLoadedFlowNode.Inputs(room) + val inputs = JoinedRoomLoadedFlowNode.Inputs(room) val roomFlowNode = aRoomFlowNode( plugins = listOf(inputs), messagesEntryPoint = fakeMessagesEntryPoint, @@ -118,9 +118,9 @@ class RoomFlowNodeTest { val roomFlowNodeTestHelper = roomFlowNode.parentNodeTestHelper() // THEN - assertThat(roomFlowNode.backstack.activeElement).isEqualTo(RoomLoadedFlowNode.NavTarget.Messages) - roomFlowNodeTestHelper.assertChildHasLifecycle(RoomLoadedFlowNode.NavTarget.Messages, Lifecycle.State.CREATED) - val messagesNode = roomFlowNode.childNode(RoomLoadedFlowNode.NavTarget.Messages)!! + assertThat(roomFlowNode.backstack.activeElement).isEqualTo(JoinedRoomLoadedFlowNode.NavTarget.Messages) + roomFlowNodeTestHelper.assertChildHasLifecycle(JoinedRoomLoadedFlowNode.NavTarget.Messages, Lifecycle.State.CREATED) + val messagesNode = roomFlowNode.childNode(JoinedRoomLoadedFlowNode.NavTarget.Messages)!! assertThat(messagesNode.id).isEqualTo(fakeMessagesEntryPoint.nodeId) } @@ -130,7 +130,7 @@ class RoomFlowNodeTest { val room = FakeMatrixRoom() val fakeMessagesEntryPoint = FakeMessagesEntryPoint() val fakeRoomDetailsEntryPoint = FakeRoomDetailsEntryPoint() - val inputs = RoomLoadedFlowNode.Inputs(room) + val inputs = JoinedRoomLoadedFlowNode.Inputs(room) val roomFlowNode = aRoomFlowNode( plugins = listOf(inputs), messagesEntryPoint = fakeMessagesEntryPoint, @@ -141,8 +141,8 @@ class RoomFlowNodeTest { // WHEN fakeMessagesEntryPoint.callback?.onRoomDetailsClicked() // THEN - roomFlowNodeTestHelper.assertChildHasLifecycle(RoomLoadedFlowNode.NavTarget.RoomDetails, Lifecycle.State.CREATED) - val roomDetailsNode = roomFlowNode.childNode(RoomLoadedFlowNode.NavTarget.RoomDetails)!! + roomFlowNodeTestHelper.assertChildHasLifecycle(JoinedRoomLoadedFlowNode.NavTarget.RoomDetails, Lifecycle.State.CREATED) + val roomDetailsNode = roomFlowNode.childNode(JoinedRoomLoadedFlowNode.NavTarget.RoomDetails)!! assertThat(roomDetailsNode.id).isEqualTo(fakeRoomDetailsEntryPoint.nodeId) } } diff --git a/appnav/src/test/kotlin/io/element/android/appnav/room/LoadingRoomStateFlowFactoryTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/room/LoadingRoomStateFlowFactoryTest.kt index 58e35b2d58..cb8ed2da32 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/room/LoadingRoomStateFlowFactoryTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/room/LoadingRoomStateFlowFactoryTest.kt @@ -18,6 +18,8 @@ package io.element.android.appnav.room import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.appnav.room.joined.LoadingRoomState +import io.element.android.appnav.room.joined.LoadingRoomStateFlowFactory import io.element.android.libraries.matrix.api.roomlist.RoomList import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SESSION_ID diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt index 5c526870e5..4534f10a74 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt @@ -17,7 +17,15 @@ package io.element.android.libraries.matrix.api.roomlist import androidx.compose.runtime.Immutable +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map +import java.util.Optional /** * Entry point for the room list api. @@ -77,4 +85,11 @@ interface RoomListService { * The state of the service as a flow. */ val state: StateFlow + + /** + * Get a flow of the room summary for a given room id. + */ + fun getUserMembershipForRoom(roomId: RoomId): Flow> } + + diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt index 70310e472e..09e0a514b1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt @@ -16,16 +16,24 @@ package io.element.android.libraries.matrix.impl.roomlist +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.roomlist.DynamicRoomList import io.element.android.libraries.matrix.api.roomlist.RoomList import io.element.android.libraries.matrix.api.roomlist.RoomListFilter import io.element.android.libraries.matrix.api.roomlist.RoomListService +import io.element.android.libraries.matrix.api.roomlist.awaitLoaded import io.element.android.libraries.matrix.api.roomlist.loadAllIncrementally +import io.element.android.libraries.matrix.impl.room.map import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn @@ -35,7 +43,9 @@ import org.matrix.rustcomponents.sdk.RoomListInput import org.matrix.rustcomponents.sdk.RoomListRange import org.matrix.rustcomponents.sdk.RoomListServiceState import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator +import org.matrix.rustcomponents.sdk.use import timber.log.Timber +import java.util.Optional import org.matrix.rustcomponents.sdk.RoomListService as InnerRustRoomListService private const val DEFAULT_PAGE_SIZE = 20 @@ -112,6 +122,24 @@ internal class RustRoomListService( } .distinctUntilChanged() .stateIn(sessionCoroutineScope, SharingStarted.Eagerly, RoomListService.State.Idle) + + override fun getUserMembershipForRoom(roomId: RoomId): Flow> { + return combine( + allRooms.loadedStateFlow(), + invites.loadedStateFlow(), + ) { _, _ -> + val membership = innerRoomListService.roomOrNull(roomId.value)?.use { + it.roomInfo().use { roomInfo -> + roomInfo.membership.map() + } + } + Optional.ofNullable(membership) + }.distinctUntilChanged() + } + + private fun RoomList.loadedStateFlow(): Flow { + return loadingState.filterIsInstance() + } } private fun RoomListServiceState.toRoomListState(): RoomListService.State { From dbe07af96d078b53d3e818be2f4b4bc87ca1236f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 03:06:38 +0000 Subject: [PATCH 02/52] Update dependency com.google.devtools.ksp to v1.9.23-1.0.20 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b05833f4f7..54cb2e3581 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ # Project android_gradle_plugin = "8.3.1" kotlin = "1.9.23" -ksp = "1.9.23-1.0.19" +ksp = "1.9.23-1.0.20" firebaseAppDistribution = "4.2.0" # AndroidX From cdadd19e6a504aa19831ea2e713ed1c93230d19e Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 5 Apr 2024 17:57:02 +0200 Subject: [PATCH 03/52] Room navigation : introduce the JoinRoomNode --- .../android/appnav/room/RoomFlowNode.kt | 49 ++-- .../appnav/room/join/JoinRoomEvents.kt | 23 ++ .../android/appnav/room/join/JoinRoomNode.kt | 55 +++++ .../appnav/room/join/JoinRoomPresenter.kt | 104 +++++++++ .../android/appnav/room/join/JoinRoomState.kt | 59 +++++ .../appnav/room/join/JoinRoomStateProvider.kt | 60 +++++ .../android/appnav/room/join/JoinRoomView.kt | 211 ++++++++++++++++++ .../appnav/room/join/di/JoinRoomModule.kt | 46 ++++ .../atomic/molecules/ButtonRowMolecule.kt | 6 +- 9 files changed, 583 insertions(+), 30 deletions(-) create mode 100644 appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomEvents.kt create mode 100644 appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt create mode 100644 appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt create mode 100644 appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt create mode 100644 appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt create mode 100644 appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt create mode 100644 appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt index dd53d6168b..beef8a883c 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt @@ -34,9 +34,9 @@ import com.bumble.appyx.navmodel.backstack.operation.newRoot import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode +import io.element.android.appnav.room.join.JoinRoomNode import io.element.android.appnav.room.joined.JoinedRoomFlowNode import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode -import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.libraries.architecture.BackstackView import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.NodeInputs @@ -64,16 +64,14 @@ class RoomFlowNode @AssistedInject constructor( @Assisted plugins: List, private val roomListService: RoomListService, private val roomMembershipObserver: RoomMembershipObserver, - private val networkMonitor: NetworkMonitor, -) : - BaseFlowNode( - backstack = BackStack( - initialElement = NavTarget.Loading, - savedStateMap = buildContext.savedStateMap, - ), - buildContext = buildContext, - plugins = plugins - ) { +) : BaseFlowNode( + backstack = BackStack( + initialElement = NavTarget.Loading, + savedStateMap = buildContext.savedStateMap, + ), + buildContext = buildContext, + plugins = plugins +) { data class Inputs( val roomId: RoomId, val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages, @@ -96,18 +94,16 @@ class RoomFlowNode @AssistedInject constructor( super.onBuilt() roomListService.getUserMembershipForRoom( inputs.roomId - ).onEach { membership -> - Timber.d("RoomMembership = $membership") - when { - membership.getOrNull() == CurrentUserMembership.JOINED -> { + ).flowOn(Dispatchers.Default) + .onEach { membership -> + Timber.d("RoomMembership = $membership") + if (membership.getOrNull() == CurrentUserMembership.JOINED) { backstack.newRoot(NavTarget.JoinedRoom) - } - else -> { + } else { backstack.newRoot(NavTarget.JoinRoom) } } - } - .flowOn(Dispatchers.Default) + .flowOn(Dispatchers.Main) .launchIn(lifecycleScope) roomMembershipObserver.updates @@ -121,7 +117,10 @@ class RoomFlowNode @AssistedInject constructor( override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { NavTarget.Loading -> loadingNode(buildContext) - NavTarget.JoinRoom -> joinRoomNode(buildContext) + NavTarget.JoinRoom -> { + val inputs = JoinRoomNode.Inputs(inputs.roomId) + createNode(buildContext, plugins = listOf(inputs)) + } NavTarget.JoinedRoom -> { val roomFlowNodeCallback = plugins() val inputs = JoinedRoomFlowNode.Inputs(inputs.roomId, initialElement = inputs.initialElement) @@ -136,16 +135,8 @@ class RoomFlowNode @AssistedInject constructor( } } - private fun joinRoomNode(buildContext: BuildContext) = node(buildContext) { - Box(modifier = it.fillMaxSize(), contentAlignment = Alignment.Center) { - Text("Unknown Room") - } - } - @Composable override fun View(modifier: Modifier) { - BackstackView( - transitionHandler = JumpToEndTransitionHandler(), - ) + BackstackView(transitionHandler = JumpToEndTransitionHandler()) } } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomEvents.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomEvents.kt new file mode 100644 index 0000000000..7679e77c63 --- /dev/null +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomEvents.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.appnav.room.join + +sealed interface JoinRoomEvents { + data object JoinRoom: JoinRoomEvents + data object AcceptInvite : JoinRoomEvents + data object DeclineInvite : JoinRoomEvents +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt new file mode 100644 index 0000000000..cccc66ddfb --- /dev/null +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.appnav.room.join + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.RoomId + +@ContributesNode(SessionScope::class) +class JoinRoomNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + presenterFactory: JoinRoomPresenter.Factory, +) : Node(buildContext, plugins = plugins) { + + data class Inputs( + val roomId: RoomId, + ) : NodeInputs + + private val inputs: Inputs = inputs() + private val presenter = presenterFactory.create(inputs.roomId) + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + JoinRoomView( + state = state, + onBackPressed = ::navigateUp, + modifier = modifier + ) + } +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt new file mode 100644 index 0000000000..5117238c6c --- /dev/null +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.appnav.room.join + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.produceState +import androidx.compose.runtime.rememberCoroutineScope +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.roomlist.RoomListService +import kotlinx.coroutines.launch +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class JoinRoomPresenter @AssistedInject constructor( + @Assisted private val roomId: RoomId, + private val matrixClient: MatrixClient, + private val roomListService: RoomListService, +) : Presenter { + + interface Factory { + fun create(roomId: RoomId): JoinRoomPresenter + } + + @Composable + override fun present(): JoinRoomState { + val userMembership by roomListService.getUserMembershipForRoom(roomId).collectAsState(initial = Optional.empty()) + val joinAuthorisationStatus = joinAuthorisationStatus(userMembership) + val roomInfo by produceState>(initialValue = AsyncData.Uninitialized, key1 = userMembership) { + when { + userMembership.isPresent -> { + val roomInfo = matrixClient.getRoom(roomId)?.let { + RoomInfo( + roomId = it.roomId, + roomName = it.displayName, + roomAlias = it.alias, + memberCount = it.activeMemberCount, + roomAvatarUrl = it.avatarUrl + ) + } + value = roomInfo?.let { AsyncData.Success(it) } ?: AsyncData.Failure(Exception("Failed to load room info")) + } + else -> { + value = AsyncData.Uninitialized + } + } + } + + val coroutineScope = rememberCoroutineScope() + + fun handleEvents(event: JoinRoomEvents) { + when (event) { + JoinRoomEvents.AcceptInvite, JoinRoomEvents.JoinRoom -> { + coroutineScope.launch { + matrixClient.joinRoom(roomId) + } + } + JoinRoomEvents.DeclineInvite -> { + coroutineScope.launch { + matrixClient.getRoom(roomId)?.use { + it.leave() + } + } + } + } + } + + return JoinRoomState( + roomInfo = roomInfo, + joinAuthorisationStatus = joinAuthorisationStatus, + currentAction = CurrentAction.None, + eventSink = ::handleEvents + ) + } + + @Composable + private fun joinAuthorisationStatus(userMembership: Optional): JoinAuthorisationStatus { + return when { + userMembership.getOrNull() == CurrentUserMembership.INVITED -> return JoinAuthorisationStatus.IsInvited + else -> JoinAuthorisationStatus.Unknown + } + } +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt new file mode 100644 index 0000000000..481fb13642 --- /dev/null +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.appnav.room.join + +import androidx.compose.runtime.Immutable +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.matrix.api.core.RoomId + +@Immutable +data class JoinRoomState( + val roomInfo: AsyncData, + val joinAuthorisationStatus: JoinAuthorisationStatus, + val currentAction: CurrentAction, + val eventSink: (JoinRoomEvents) -> Unit +) + +data class RoomInfo( + val roomId: RoomId, + val roomName: String, + val roomAlias: String?, + val memberCount: Long?, + val roomAvatarUrl: String?, +) { + fun avatarData(size: AvatarSize): AvatarData { + return AvatarData( + id = roomId.value, + name = roomName, + url = roomAvatarUrl, + size = size, + ) + } +} + +enum class JoinAuthorisationStatus { + IsInvited, + CanKnock, + CanJoin, + Unknown, +} + +sealed interface CurrentAction { + data object None : CurrentAction +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt new file mode 100644 index 0000000000..928edb4ce4 --- /dev/null +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.appnav.room.join + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.matrix.api.core.RoomId + +open class JoinRoomStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aJoinRoomState( + roomInfo = AsyncData.Uninitialized + ), + aJoinRoomState( + joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin + ), + aJoinRoomState( + joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock + ), + aJoinRoomState( + joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited + ), + ) +} + +fun aJoinRoomState( + roomInfo: AsyncData = AsyncData.Success( + RoomInfo( + roomId = RoomId("@exa:matrix.org"), + roomName = "Element x android", + roomAlias = "#exa:matrix.org", + memberCount = null, + roomAvatarUrl = null + ) + ), + joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown, + currentAction: CurrentAction = CurrentAction.None, + eventSink: (JoinRoomEvents) -> Unit = {} +) = JoinRoomState( + roomInfo = roomInfo, + joinAuthorisationStatus = joinAuthorisationStatus, + currentAction = currentAction, + eventSink = eventSink +) + diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt new file mode 100644 index 0000000000..9fcda27e25 --- /dev/null +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.appnav.room.join + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.PreviewLightDark +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom +import io.element.android.libraries.designsystem.atomic.molecules.ButtonRowMolecule +import io.element.android.libraries.designsystem.atomic.molecules.IconTitlePlaceholdersRowMolecule +import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage +import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.ButtonSize +import io.element.android.libraries.designsystem.theme.components.OutlinedButton +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun JoinRoomView( + state: JoinRoomState, + onBackPressed: () -> Unit, + modifier: Modifier = Modifier, +) { + HeaderFooterPage( + modifier = modifier, + topBar = { + JoinRoomTopBar(asyncRoomInfo = state.roomInfo, onBackClicked = onBackPressed) + }, + content = { + JoinRoomContent(state = state) + }, + footer = { + JoinRoomFooter( + joinAuthorisationStatus = state.joinAuthorisationStatus, + onAcceptInvite = { + state.eventSink(JoinRoomEvents.AcceptInvite) + }, + onDeclineInvite = { + state.eventSink(JoinRoomEvents.DeclineInvite) + }, + onJoinRoom = { + state.eventSink(JoinRoomEvents.JoinRoom) + }, + ) + } + ) +} + +@Composable +private fun JoinRoomFooter( + joinAuthorisationStatus: JoinAuthorisationStatus, + onAcceptInvite: () -> Unit, + onDeclineInvite: () -> Unit, + onJoinRoom: () -> Unit, + modifier: Modifier = Modifier, +) { + when (joinAuthorisationStatus) { + JoinAuthorisationStatus.IsInvited -> { + ButtonRowMolecule(modifier = modifier, horizontalArrangement = Arrangement.spacedBy(20.dp)) { + OutlinedButton( + text = stringResource(CommonStrings.action_decline), + onClick = onDeclineInvite, + modifier = Modifier.weight(1f), + size = ButtonSize.Medium, + ) + Button( + text = stringResource(CommonStrings.action_accept), + onClick = onAcceptInvite, + modifier = Modifier.weight(1f), + size = ButtonSize.Medium, + ) + } + } + // TODO handle all cases properly + else -> { + Button( + text = stringResource(CommonStrings.action_join), + onClick = onJoinRoom, + modifier = modifier.fillMaxWidth(), + size = ButtonSize.Medium, + ) + } + } +} + +@Composable +private fun JoinRoomContent( + state: JoinRoomState, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier.padding(all = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(modifier = Modifier.height(80.dp)) + when (state.roomInfo) { + is AsyncData.Success -> { + val roomInfo = state.roomInfo.data + Avatar(avatarData = roomInfo.avatarData(AvatarSize.RoomHeader)) + } + else -> { + PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) + } + } + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = "Preview is not available", + style = ElementTheme.typography.fontHeadingMdBold, + textAlign = TextAlign.Center, + color = ElementTheme.colors.textPrimary, + ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = "You must be a member of this room to view the message history.", + style = ElementTheme.typography.fontBodyMdRegular, + textAlign = TextAlign.Center, + color = ElementTheme.colors.textSecondary, + ) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun JoinRoomTopBar( + asyncRoomInfo: AsyncData, + onBackClicked: () -> Unit, +) { + TopAppBar( + navigationIcon = { + BackButton(onClick = onBackClicked) + }, + title = { + when (asyncRoomInfo) { + is AsyncData.Success -> { + val roomInfo = asyncRoomInfo.data + RoomAvatarAndNameRow(roomName = roomInfo.roomName, roomAvatar = roomInfo.avatarData(AvatarSize.TimelineRoom)) + } + else -> { + IconTitlePlaceholdersRowMolecule(iconSize = AvatarSize.TimelineRoom.dp) + } + } + }, + ) +} + +@Composable +private fun RoomAvatarAndNameRow( + roomName: String, + roomAvatar: AvatarData, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically + ) { + Avatar(roomAvatar) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = roomName, + style = ElementTheme.typography.fontBodyLgMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } +} + +@PreviewLightDark +@Composable +fun JoinRoomViewPreview(@PreviewParameter(JoinRoomStateProvider::class) state: JoinRoomState) = ElementPreview { + JoinRoomView( + state = state, + onBackPressed = { } + ) +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt new file mode 100644 index 0000000000..fa7635a312 --- /dev/null +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.appnav.room.join.di + +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import io.element.android.appnav.room.join.JoinRoomPresenter +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.roomlist.RoomListService + +@Module +@ContributesTo(SessionScope::class) +object JoinRoomModule { + @Provides + fun providesJoinRoomPresenterFactory( + roomListService: RoomListService, + client: MatrixClient, + ): JoinRoomPresenter.Factory { + return object : JoinRoomPresenter.Factory { + override fun create(roomId: RoomId): JoinRoomPresenter { + return JoinRoomPresenter( + roomId = roomId, + matrixClient = client, + roomListService = roomListService + ) + } + } + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonRowMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonRowMolecule.kt index 9388b54880..f6f5c3cb81 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonRowMolecule.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonRowMolecule.kt @@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -29,11 +30,14 @@ import io.element.android.libraries.designsystem.theme.components.TextButton @Composable fun ButtonRowMolecule( modifier: Modifier = Modifier, + horizontalArrangement: Arrangement.Horizontal = Arrangement.SpaceBetween, + verticalAlignment: Alignment.Vertical = Alignment.Top, content: @Composable RowScope.() -> Unit ) { Row( modifier = modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween + horizontalArrangement = horizontalArrangement, + verticalAlignment = verticalAlignment, ) { content() } From 01d45377f688b0b9d157dda0d66bbbeaa5661b1e Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 5 Apr 2024 17:57:38 +0200 Subject: [PATCH 04/52] Room navigation : do not replay RoomMembership Changes --- .../libraries/matrix/api/room/RoomMembershipObserver.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembershipObserver.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembershipObserver.kt index ed6f3fae26..24610a64c9 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembershipObserver.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembershipObserver.kt @@ -28,10 +28,10 @@ class RoomMembershipObserver { val change: MembershipChange, ) - private val _updates = MutableSharedFlow(replay = 1) + private val _updates = MutableSharedFlow(extraBufferCapacity = 10) val updates = _updates.asSharedFlow() - fun notifyUserLeftRoom(roomId: RoomId) { - _updates.tryEmit(RoomMembershipUpdate(roomId, false, MembershipChange.LEFT)) + suspend fun notifyUserLeftRoom(roomId: RoomId) { + _updates.emit(RoomMembershipUpdate(roomId, false, MembershipChange.LEFT)) } } From 650256e59fe72c3ad5fbf1e650b92b613d54acc3 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 5 Apr 2024 18:41:15 +0200 Subject: [PATCH 05/52] Join Room : add member count --- .../appnav/room/join/JoinRoomPresenter.kt | 2 +- .../android/appnav/room/join/JoinRoomState.kt | 4 ++- .../android/appnav/room/join/JoinRoomView.kt | 29 ++++++++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt index 5117238c6c..3dda190d33 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt @@ -50,7 +50,7 @@ class JoinRoomPresenter @AssistedInject constructor( val roomInfo by produceState>(initialValue = AsyncData.Uninitialized, key1 = userMembership) { when { userMembership.isPresent -> { - val roomInfo = matrixClient.getRoom(roomId)?.let { + val roomInfo = matrixClient.getRoom(roomId)?.use { RoomInfo( roomId = it.roomId, roomName = it.displayName, diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt index 481fb13642..2e95987d97 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt @@ -28,7 +28,9 @@ data class JoinRoomState( val joinAuthorisationStatus: JoinAuthorisationStatus, val currentAction: CurrentAction, val eventSink: (JoinRoomEvents) -> Unit -) +){ + val showMemberCount = roomInfo.dataOrNull()?.memberCount != null +} data class RoomInfo( val roomId: RoomId, diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt index 9fcda27e25..9a4b805176 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt @@ -16,14 +16,18 @@ package io.element.android.appnav.room.join +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -35,6 +39,7 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom import io.element.android.libraries.designsystem.atomic.molecules.ButtonRowMolecule @@ -47,6 +52,7 @@ import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.ButtonSize +import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar @@ -129,7 +135,6 @@ private fun JoinRoomContent( modifier = modifier.padding(all = 16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - Spacer(modifier = Modifier.height(80.dp)) when (state.roomInfo) { is AsyncData.Success -> { val roomInfo = state.roomInfo.data @@ -153,6 +158,28 @@ private fun JoinRoomContent( textAlign = TextAlign.Center, color = ElementTheme.colors.textSecondary, ) + if (state.showMemberCount) { + Spacer(modifier = Modifier.height(8.dp)) + Row( + modifier = Modifier + .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) + .widthIn(min = 48.dp) + .padding(all = 2.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp) + ) { + Icon( + imageVector = CompoundIcons.UserProfile(), + contentDescription = null, + tint = ElementTheme.colors.iconSecondary, + ) + Text( + text = "${state.roomInfo.dataOrNull()?.memberCount}", + style = ElementTheme.typography.fontBodySmMedium, + color = ElementTheme.colors.textSecondary, + ) + } + } } } From e57ee00a9153090c0b1dad12268484313c10f024 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 8 Apr 2024 15:54:08 +0200 Subject: [PATCH 06/52] Join Room : improve a bit --- .../appnav/room/join/JoinRoomPresenter.kt | 8 ++- .../android/appnav/room/join/JoinRoomView.kt | 50 +++++++++++-------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt index 3dda190d33..d80fb99b3e 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt @@ -48,7 +48,7 @@ class JoinRoomPresenter @AssistedInject constructor( val userMembership by roomListService.getUserMembershipForRoom(roomId).collectAsState(initial = Optional.empty()) val joinAuthorisationStatus = joinAuthorisationStatus(userMembership) val roomInfo by produceState>(initialValue = AsyncData.Uninitialized, key1 = userMembership) { - when { + value = when { userMembership.isPresent -> { val roomInfo = matrixClient.getRoom(roomId)?.use { RoomInfo( @@ -59,11 +59,9 @@ class JoinRoomPresenter @AssistedInject constructor( roomAvatarUrl = it.avatarUrl ) } - value = roomInfo?.let { AsyncData.Success(it) } ?: AsyncData.Failure(Exception("Failed to load room info")) - } - else -> { - value = AsyncData.Uninitialized + roomInfo?.let { AsyncData.Success(it) } ?: AsyncData.Failure(Exception("Failed to load room info")) } + else -> AsyncData.Uninitialized } } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt index 9a4b805176..eff9181c11 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt @@ -23,7 +23,6 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn @@ -132,7 +131,9 @@ private fun JoinRoomContent( modifier: Modifier = Modifier, ) { Column( - modifier = modifier.padding(all = 16.dp), + modifier = modifier + .fillMaxWidth() + .padding(all = 16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { when (state.roomInfo) { @@ -159,30 +160,35 @@ private fun JoinRoomContent( color = ElementTheme.colors.textSecondary, ) if (state.showMemberCount) { - Spacer(modifier = Modifier.height(8.dp)) - Row( - modifier = Modifier - .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) - .widthIn(min = 48.dp) - .padding(all = 2.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp) - ) { - Icon( - imageVector = CompoundIcons.UserProfile(), - contentDescription = null, - tint = ElementTheme.colors.iconSecondary, - ) - Text( - text = "${state.roomInfo.dataOrNull()?.memberCount}", - style = ElementTheme.typography.fontBodySmMedium, - color = ElementTheme.colors.textSecondary, - ) - } + JoinRoomMembersCount(memberCount = state.roomInfo.dataOrNull()?.memberCount ?: 0) } } } +@Composable +fun JoinRoomMembersCount(memberCount: Long) { + Spacer(modifier = Modifier.height(8.dp)) + Row( + modifier = Modifier + .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) + .widthIn(min = 48.dp) + .padding(all = 2.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp) + ) { + Icon( + imageVector = CompoundIcons.UserProfile(), + contentDescription = null, + tint = ElementTheme.colors.iconSecondary, + ) + Text( + text = "$memberCount", + style = ElementTheme.typography.fontBodySmMedium, + color = ElementTheme.colors.textSecondary, + ) + } +} + @OptIn(ExperimentalMaterial3Api::class) @Composable private fun JoinRoomTopBar( From f586114458eab40cef48a935c8ac47332d0bbabb Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 8 Apr 2024 17:22:13 +0200 Subject: [PATCH 07/52] Room navigation : rename module invitelist to invite --- .../io/element/android/appnav/LoggedInFlowNode.kt | 6 +----- features/{invitelist => invite}/api/build.gradle.kts | 2 +- .../features/invite}/api/InviteListEntryPoint.kt | 2 +- .../android/features/invite}/api/SeenInvitesStore.kt | 2 +- features/{invitelist => invite}/impl/build.gradle.kts | 6 +++--- .../invite}/impl/DefaultInviteListEntryPoint.kt | 4 ++-- .../features/invite}/impl/DefaultSeenInvitesStore.kt | 4 ++-- .../android/features/invite}/impl/InviteListEvents.kt | 4 ++-- .../android/features/invite}/impl/InviteListNode.kt | 4 ++-- .../features/invite}/impl/InviteListPresenter.kt | 8 ++++---- .../android/features/invite}/impl/InviteListState.kt | 4 ++-- .../features/invite}/impl/InviteListStateProvider.kt | 6 +++--- .../android/features/invite}/impl/InviteListView.kt | 4 ++-- .../invite}/impl/components/InviteSummaryRow.kt | 10 +++++----- .../invite}/impl/model/InviteListInviteSummary.kt | 2 +- .../impl/model/InviteListInviteSummaryProvider.kt | 2 +- .../impl/src/main/res/values-be/translations.xml | 0 .../impl/src/main/res/values-bg/translations.xml | 0 .../impl/src/main/res/values-cs/translations.xml | 0 .../impl/src/main/res/values-de/translations.xml | 0 .../impl/src/main/res/values-es/translations.xml | 0 .../impl/src/main/res/values-fr/translations.xml | 0 .../impl/src/main/res/values-hu/translations.xml | 0 .../impl/src/main/res/values-in/translations.xml | 0 .../impl/src/main/res/values-it/translations.xml | 0 .../impl/src/main/res/values-ro/translations.xml | 0 .../impl/src/main/res/values-ru/translations.xml | 0 .../impl/src/main/res/values-sk/translations.xml | 0 .../impl/src/main/res/values-sv/translations.xml | 0 .../impl/src/main/res/values-uk/translations.xml | 0 .../impl/src/main/res/values-zh-rTW/translations.xml | 0 .../impl/src/main/res/values/localazy.xml | 0 .../features/invite}/impl/InviteListPresenterTests.kt | 6 +++--- features/{invitelist => invite}/test/build.gradle.kts | 4 ++-- .../features/invite}/test/FakeSeenInvitesStore.kt | 4 ++-- features/roomlist/impl/build.gradle.kts | 4 ++-- .../impl/datasource/DefaultInviteStateDataSource.kt | 2 +- .../datasource/DefaultInviteStateDataSourceTest.kt | 2 +- samples/minimal/build.gradle.kts | 2 +- .../element/android/samples/minimal/RoomListScreen.kt | 2 +- tools/localazy/config.json | 2 +- 41 files changed, 47 insertions(+), 51 deletions(-) rename features/{invitelist => invite}/api/build.gradle.kts (92%) rename features/{invitelist/api/src/main/kotlin/io/element/android/features/invitelist => invite/api/src/main/kotlin/io/element/android/features/invite}/api/InviteListEntryPoint.kt (96%) rename features/{invitelist/api/src/main/kotlin/io/element/android/features/invitelist => invite/api/src/main/kotlin/io/element/android/features/invite}/api/SeenInvitesStore.kt (94%) rename features/{invitelist => invite}/impl/build.gradle.kts (91%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/DefaultInviteListEntryPoint.kt (92%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/DefaultSeenInvitesStore.kt (94%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/InviteListEvents.kt (88%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/InviteListNode.kt (93%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/InviteListPresenter.kt (96%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/InviteListState.kt (90%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/InviteListStateProvider.kt (93%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/InviteListView.kt (98%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/components/InviteSummaryRow.kt (94%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/model/InviteListInviteSummary.kt (96%) rename features/{invitelist/impl/src/main/kotlin/io/element/android/features/invitelist => invite/impl/src/main/kotlin/io/element/android/features/invite}/impl/model/InviteListInviteSummaryProvider.kt (96%) rename features/{invitelist => invite}/impl/src/main/res/values-be/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-bg/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-cs/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-de/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-es/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-fr/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-hu/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-in/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-it/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-ro/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-ru/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-sk/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-sv/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-uk/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values-zh-rTW/translations.xml (100%) rename features/{invitelist => invite}/impl/src/main/res/values/localazy.xml (100%) rename features/{invitelist/impl/src/test/kotlin/io/element/android/features/invitelist => invite/impl/src/test/kotlin/io/element/android/features/invite}/impl/InviteListPresenterTests.kt (99%) rename features/{invitelist => invite}/test/build.gradle.kts (88%) rename features/{invitelist/test/src/main/kotlin/io/element/android/features/invitelist => invite/test/src/main/kotlin/io/element/android/features/invite}/test/FakeSeenInvitesStore.kt (90%) 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 8ff7ecfaa8..8ba98e5a6b 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -48,7 +48,7 @@ import io.element.android.features.createroom.api.CreateRoomEntryPoint 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.invitelist.api.InviteListEntryPoint +import io.element.android.features.invite.api.InviteListEntryPoint import io.element.android.features.lockscreen.api.LockScreenEntryPoint import io.element.android.features.lockscreen.api.LockScreenLockState import io.element.android.features.lockscreen.api.LockScreenService @@ -350,10 +350,6 @@ class LoggedInFlowNode @AssistedInject constructor( backstack.pop() } - override fun onInviteClicked(roomId: RoomId) { - backstack.push(NavTarget.Room(roomId)) - } - override fun onInviteAccepted(roomId: RoomId) { backstack.push(NavTarget.Room(roomId)) } diff --git a/features/invitelist/api/build.gradle.kts b/features/invite/api/build.gradle.kts similarity index 92% rename from features/invitelist/api/build.gradle.kts rename to features/invite/api/build.gradle.kts index 6ea2b8a49d..1781ee93ae 100644 --- a/features/invitelist/api/build.gradle.kts +++ b/features/invite/api/build.gradle.kts @@ -19,7 +19,7 @@ plugins { } android { - namespace = "io.element.android.features.invitelist.api" + namespace = "io.element.android.features.invite.api" } dependencies { diff --git a/features/invitelist/api/src/main/kotlin/io/element/android/features/invitelist/api/InviteListEntryPoint.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteListEntryPoint.kt similarity index 96% rename from features/invitelist/api/src/main/kotlin/io/element/android/features/invitelist/api/InviteListEntryPoint.kt rename to features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteListEntryPoint.kt index 95d2c94f50..6abfe8f518 100644 --- a/features/invitelist/api/src/main/kotlin/io/element/android/features/invitelist/api/InviteListEntryPoint.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteListEntryPoint.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invitelist.api +package io.element.android.features.invite.api import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node diff --git a/features/invitelist/api/src/main/kotlin/io/element/android/features/invitelist/api/SeenInvitesStore.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt similarity index 94% rename from features/invitelist/api/src/main/kotlin/io/element/android/features/invitelist/api/SeenInvitesStore.kt rename to features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt index ac143b8740..e34b17cee8 100644 --- a/features/invitelist/api/src/main/kotlin/io/element/android/features/invitelist/api/SeenInvitesStore.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/SeenInvitesStore.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invitelist.api +package io.element.android.features.invite.api import io.element.android.libraries.matrix.api.core.RoomId import kotlinx.coroutines.flow.Flow diff --git a/features/invitelist/impl/build.gradle.kts b/features/invite/impl/build.gradle.kts similarity index 91% rename from features/invitelist/impl/build.gradle.kts rename to features/invite/impl/build.gradle.kts index 110eb7946e..7a0b0db372 100644 --- a/features/invitelist/impl/build.gradle.kts +++ b/features/invite/impl/build.gradle.kts @@ -22,7 +22,7 @@ plugins { } android { - namespace = "io.element.android.features.invitelist.impl" + namespace = "io.element.android.features.invite.impl" } anvil { @@ -32,7 +32,7 @@ anvil { dependencies { implementation(projects.anvilannotations) anvil(projects.anvilcodegen) - api(projects.features.invitelist.api) + api(projects.features.invite.api) implementation(libs.androidx.datastore.preferences) implementation(projects.libraries.core) implementation(projects.libraries.architecture) @@ -50,7 +50,7 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.push.test) - testImplementation(projects.features.invitelist.test) + testImplementation(projects.features.invite.test) testImplementation(projects.services.analytics.test) testImplementation(projects.tests.testutils) diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/DefaultInviteListEntryPoint.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/DefaultInviteListEntryPoint.kt similarity index 92% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/DefaultInviteListEntryPoint.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/DefaultInviteListEntryPoint.kt index 5c2fc780d7..03e7a57dae 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/DefaultInviteListEntryPoint.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/DefaultInviteListEntryPoint.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl +package io.element.android.features.invite.impl import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.features.invitelist.api.InviteListEntryPoint +import io.element.android.features.invite.api.InviteListEntryPoint import io.element.android.libraries.architecture.createNode import io.element.android.libraries.di.AppScope import javax.inject.Inject diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/DefaultSeenInvitesStore.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/DefaultSeenInvitesStore.kt similarity index 94% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/DefaultSeenInvitesStore.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/DefaultSeenInvitesStore.kt index 1564b2fa83..bf0423914e 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/DefaultSeenInvitesStore.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/DefaultSeenInvitesStore.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl +package io.element.android.features.invite.impl import android.content.Context import androidx.datastore.core.DataStore @@ -23,7 +23,7 @@ import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringSetPreferencesKey import androidx.datastore.preferences.preferencesDataStore import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.features.invitelist.api.SeenInvitesStore +import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.libraries.di.ApplicationContext import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.core.RoomId diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListEvents.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListEvents.kt similarity index 88% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListEvents.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListEvents.kt index ae4b74bb2c..7bf58aba7a 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListEvents.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListEvents.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl +package io.element.android.features.invite.impl -import io.element.android.features.invitelist.impl.model.InviteListInviteSummary +import io.element.android.features.invite.impl.model.InviteListInviteSummary sealed interface InviteListEvents { data class AcceptInvite(val invite: InviteListInviteSummary) : InviteListEvents diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListNode.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListNode.kt similarity index 93% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListNode.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListNode.kt index 31d742e4e7..1f3236e916 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListNode.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListNode.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl +package io.element.android.features.invite.impl import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -25,7 +25,7 @@ import com.bumble.appyx.core.plugin.plugins import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode -import io.element.android.features.invitelist.api.InviteListEntryPoint +import io.element.android.features.invite.api.InviteListEntryPoint import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.core.RoomId diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListPresenter.kt similarity index 96% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListPresenter.kt index aa7cead66e..f616450d25 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListPresenter.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl +package io.element.android.features.invite.impl import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -26,9 +26,9 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import im.vector.app.features.analytics.plan.JoinedRoom -import io.element.android.features.invitelist.api.SeenInvitesStore -import io.element.android.features.invitelist.impl.model.InviteListInviteSummary -import io.element.android.features.invitelist.impl.model.InviteSender +import io.element.android.features.invite.api.SeenInvitesStore +import io.element.android.features.invite.impl.model.InviteListInviteSummary +import io.element.android.features.invite.impl.model.InviteSender import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListState.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListState.kt similarity index 90% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListState.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListState.kt index b576861475..42d73de547 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListState.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListState.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl +package io.element.android.features.invite.impl import androidx.compose.runtime.Immutable -import io.element.android.features.invitelist.impl.model.InviteListInviteSummary +import io.element.android.features.invite.impl.model.InviteListInviteSummary import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.RoomId import kotlinx.collections.immutable.ImmutableList diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListStateProvider.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListStateProvider.kt similarity index 93% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListStateProvider.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListStateProvider.kt index e61bd9ff93..5f1d5dcc0f 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListStateProvider.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListStateProvider.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl +package io.element.android.features.invite.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.features.invitelist.impl.model.InviteListInviteSummary -import io.element.android.features.invitelist.impl.model.InviteSender +import io.element.android.features.invite.impl.model.InviteListInviteSummary +import io.element.android.features.invite.impl.model.InviteSender import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListView.kt similarity index 98% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListView.kt index ff8ba55c0b..34da18f02f 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListView.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl +package io.element.android.features.invite.impl import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -36,7 +36,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme -import io.element.android.features.invitelist.impl.components.InviteSummaryRow +import io.element.android.features.invite.impl.components.InviteSummaryRow import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/components/InviteSummaryRow.kt similarity index 94% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/components/InviteSummaryRow.kt index 7c3c1ad1db..0987f6cf57 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/components/InviteSummaryRow.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl.components +package io.element.android.features.invite.impl.components import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -40,10 +40,10 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme -import io.element.android.features.invitelist.impl.R -import io.element.android.features.invitelist.impl.model.InviteListInviteSummary -import io.element.android.features.invitelist.impl.model.InviteListInviteSummaryProvider -import io.element.android.features.invitelist.impl.model.InviteSender +import io.element.android.features.invite.impl.R +import io.element.android.features.invite.impl.model.InviteListInviteSummary +import io.element.android.features.invite.impl.model.InviteListInviteSummaryProvider +import io.element.android.features.invite.impl.model.InviteSender import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.preview.ElementPreview diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/model/InviteListInviteSummary.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/model/InviteListInviteSummary.kt similarity index 96% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/model/InviteListInviteSummary.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/model/InviteListInviteSummary.kt index 9f74b90142..e17dcc997c 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/model/InviteListInviteSummary.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/model/InviteListInviteSummary.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl.model +package io.element.android.features.invite.impl.model import androidx.compose.runtime.Immutable import io.element.android.libraries.designsystem.components.avatar.AvatarData diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/model/InviteListInviteSummaryProvider.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/model/InviteListInviteSummaryProvider.kt similarity index 96% rename from features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/model/InviteListInviteSummaryProvider.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/model/InviteListInviteSummaryProvider.kt index c872d05817..11f6742345 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/model/InviteListInviteSummaryProvider.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/model/InviteListInviteSummaryProvider.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl.model +package io.element.android.features.invite.impl.model import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.matrix.api.core.RoomId diff --git a/features/invitelist/impl/src/main/res/values-be/translations.xml b/features/invite/impl/src/main/res/values-be/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-be/translations.xml rename to features/invite/impl/src/main/res/values-be/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-bg/translations.xml b/features/invite/impl/src/main/res/values-bg/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-bg/translations.xml rename to features/invite/impl/src/main/res/values-bg/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-cs/translations.xml b/features/invite/impl/src/main/res/values-cs/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-cs/translations.xml rename to features/invite/impl/src/main/res/values-cs/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-de/translations.xml b/features/invite/impl/src/main/res/values-de/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-de/translations.xml rename to features/invite/impl/src/main/res/values-de/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-es/translations.xml b/features/invite/impl/src/main/res/values-es/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-es/translations.xml rename to features/invite/impl/src/main/res/values-es/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-fr/translations.xml b/features/invite/impl/src/main/res/values-fr/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-fr/translations.xml rename to features/invite/impl/src/main/res/values-fr/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-hu/translations.xml b/features/invite/impl/src/main/res/values-hu/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-hu/translations.xml rename to features/invite/impl/src/main/res/values-hu/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-in/translations.xml b/features/invite/impl/src/main/res/values-in/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-in/translations.xml rename to features/invite/impl/src/main/res/values-in/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-it/translations.xml b/features/invite/impl/src/main/res/values-it/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-it/translations.xml rename to features/invite/impl/src/main/res/values-it/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-ro/translations.xml b/features/invite/impl/src/main/res/values-ro/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-ro/translations.xml rename to features/invite/impl/src/main/res/values-ro/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-ru/translations.xml b/features/invite/impl/src/main/res/values-ru/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-ru/translations.xml rename to features/invite/impl/src/main/res/values-ru/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-sk/translations.xml b/features/invite/impl/src/main/res/values-sk/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-sk/translations.xml rename to features/invite/impl/src/main/res/values-sk/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-sv/translations.xml b/features/invite/impl/src/main/res/values-sv/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-sv/translations.xml rename to features/invite/impl/src/main/res/values-sv/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-uk/translations.xml b/features/invite/impl/src/main/res/values-uk/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-uk/translations.xml rename to features/invite/impl/src/main/res/values-uk/translations.xml diff --git a/features/invitelist/impl/src/main/res/values-zh-rTW/translations.xml b/features/invite/impl/src/main/res/values-zh-rTW/translations.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values-zh-rTW/translations.xml rename to features/invite/impl/src/main/res/values-zh-rTW/translations.xml diff --git a/features/invitelist/impl/src/main/res/values/localazy.xml b/features/invite/impl/src/main/res/values/localazy.xml similarity index 100% rename from features/invitelist/impl/src/main/res/values/localazy.xml rename to features/invite/impl/src/main/res/values/localazy.xml diff --git a/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/InviteListPresenterTests.kt similarity index 99% rename from features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt rename to features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/InviteListPresenterTests.kt index fa0cf663a2..b9acd5eb0b 100644 --- a/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/InviteListPresenterTests.kt @@ -14,15 +14,15 @@ * limitations under the License. */ -package io.element.android.features.invitelist.impl +package io.element.android.features.invite.impl import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.TurbineTestContext import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.invitelist.api.SeenInvitesStore -import io.element.android.features.invitelist.test.FakeSeenInvitesStore +import io.element.android.features.invite.api.SeenInvitesStore +import io.element.android.features.invite.test.FakeSeenInvitesStore import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize diff --git a/features/invitelist/test/build.gradle.kts b/features/invite/test/build.gradle.kts similarity index 88% rename from features/invitelist/test/build.gradle.kts rename to features/invite/test/build.gradle.kts index ce9b0dabe4..44d9d3030c 100644 --- a/features/invitelist/test/build.gradle.kts +++ b/features/invite/test/build.gradle.kts @@ -19,11 +19,11 @@ plugins { } android { - namespace = "io.element.android.features.invitelist.test" + namespace = "io.element.android.features.invite.test" } dependencies { implementation(libs.coroutines.core) implementation(projects.libraries.matrix.api) - api(projects.features.invitelist.api) + api(projects.features.invite.api) } diff --git a/features/invitelist/test/src/main/kotlin/io/element/android/features/invitelist/test/FakeSeenInvitesStore.kt b/features/invite/test/src/main/kotlin/io/element/android/features/invite/test/FakeSeenInvitesStore.kt similarity index 90% rename from features/invitelist/test/src/main/kotlin/io/element/android/features/invitelist/test/FakeSeenInvitesStore.kt rename to features/invite/test/src/main/kotlin/io/element/android/features/invite/test/FakeSeenInvitesStore.kt index 94b232b2ac..f2a21ac768 100644 --- a/features/invitelist/test/src/main/kotlin/io/element/android/features/invitelist/test/FakeSeenInvitesStore.kt +++ b/features/invite/test/src/main/kotlin/io/element/android/features/invite/test/FakeSeenInvitesStore.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package io.element.android.features.invitelist.test +package io.element.android.features.invite.test -import io.element.android.features.invitelist.api.SeenInvitesStore +import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.libraries.matrix.api.core.RoomId import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow diff --git a/features/roomlist/impl/build.gradle.kts b/features/roomlist/impl/build.gradle.kts index 207be1df5b..ff67ebe42a 100644 --- a/features/roomlist/impl/build.gradle.kts +++ b/features/roomlist/impl/build.gradle.kts @@ -53,7 +53,7 @@ dependencies { implementation(projects.libraries.indicator.api) implementation(projects.libraries.deeplink) implementation(projects.libraries.preferences.api) - implementation(projects.features.invitelist.api) + implementation(projects.features.invite.api) implementation(projects.features.networkmonitor.api) implementation(projects.features.leaveroom.api) implementation(projects.services.analytics.api) @@ -75,7 +75,7 @@ dependencies { testImplementation(projects.libraries.indicator.impl) testImplementation(projects.libraries.permissions.noop) testImplementation(projects.libraries.preferences.test) - testImplementation(projects.features.invitelist.test) + testImplementation(projects.features.invite.test) testImplementation(projects.services.analytics.test) testImplementation(projects.features.networkmonitor.test) testImplementation(projects.tests.testutils) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSource.kt index 9057bf23ae..16baf4e41b 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSource.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSource.kt @@ -24,7 +24,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.features.invitelist.api.SeenInvitesStore +import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.roomlist.impl.InvitesState import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.SessionScope diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSourceTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSourceTest.kt index 802d8ee40f..a1e08cd93b 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSourceTest.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSourceTest.kt @@ -20,7 +20,7 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.invitelist.test.FakeSeenInvitesStore +import io.element.android.features.invite.test.FakeSeenInvitesStore import io.element.android.features.roomlist.impl.InvitesState import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID_2 diff --git a/samples/minimal/build.gradle.kts b/samples/minimal/build.gradle.kts index 7a3540e7eb..402d1a48b8 100644 --- a/samples/minimal/build.gradle.kts +++ b/samples/minimal/build.gradle.kts @@ -56,7 +56,7 @@ dependencies { implementation(projects.libraries.eventformatter.impl) implementation(projects.libraries.preferences.impl) implementation(projects.libraries.indicator.impl) - implementation(projects.features.invitelist.impl) + implementation(projects.features.invite.impl) implementation(projects.features.roomlist.impl) implementation(projects.features.leaveroom.impl) implementation(projects.features.login.impl) diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt index 264a754e73..48f629af4d 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt @@ -20,7 +20,7 @@ import android.content.Context import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.Modifier -import io.element.android.features.invitelist.impl.DefaultSeenInvitesStore +import io.element.android.features.invite.impl.DefaultSeenInvitesStore import io.element.android.features.leaveroom.impl.LeaveRoomPresenterImpl import io.element.android.features.networkmonitor.impl.NetworkMonitorImpl import io.element.android.features.roomlist.impl.RoomListPresenter diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 566ea071e0..35e13730c2 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -33,7 +33,7 @@ ] }, { - "name" : ":features:invitelist:impl", + "name" : ":features:invite:impl", "includeRegex" : [ "screen_invites_.*" ] From 7d5988492218382a19ef7d0840c547029e750622 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 8 Apr 2024 21:18:25 +0200 Subject: [PATCH 08/52] Room navigation : refactor Invites so we can use it in other places --- .../impl/DefaultInviteListEntryPoint.kt | 1 + .../impl/{ => invitelist}/InviteListEvents.kt | 10 +- .../impl/{ => invitelist}/InviteListNode.kt | 5 +- .../{ => invitelist}/InviteListPresenter.kt | 89 +++---------- .../impl/{ => invitelist}/InviteListState.kt | 16 +-- .../InviteListStateProvider.kt | 37 +++--- .../impl/{ => invitelist}/InviteListView.kt | 71 ++--------- .../response/AcceptDeclineInviteEvents.kt | 26 ++++ .../impl/response/AcceptDeclineInviteNode.kt | 46 +++++++ .../response/AcceptDeclineInvitePresenter.kt | 120 ++++++++++++++++++ .../impl/response/AcceptDeclineInviteState.kt | 34 +++++ .../AcceptDeclineInviteStateProvider.kt | 59 +++++++++ .../impl/response/AcceptDeclineInviteView.kt | 111 ++++++++++++++++ .../invite/impl/InviteListPresenterTests.kt | 3 + 14 files changed, 463 insertions(+), 165 deletions(-) rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/{ => invitelist}/InviteListEvents.kt (73%) rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/{ => invitelist}/InviteListNode.kt (93%) rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/{ => invitelist}/InviteListPresenter.kt (56%) rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/{ => invitelist}/InviteListState.kt (61%) rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/{ => invitelist}/InviteListStateProvider.kt (64%) rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/{ => invitelist}/InviteListView.kt (65%) create mode 100644 features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteEvents.kt create mode 100644 features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteNode.kt create mode 100644 features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt create mode 100644 features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteState.kt create mode 100644 features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteStateProvider.kt create mode 100644 features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/DefaultInviteListEntryPoint.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/DefaultInviteListEntryPoint.kt index 03e7a57dae..5e464a79bc 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/DefaultInviteListEntryPoint.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/DefaultInviteListEntryPoint.kt @@ -21,6 +21,7 @@ import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import com.squareup.anvil.annotations.ContributesBinding import io.element.android.features.invite.api.InviteListEntryPoint +import io.element.android.features.invite.impl.invitelist.InviteListNode import io.element.android.libraries.architecture.createNode import io.element.android.libraries.di.AppScope import javax.inject.Inject diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListEvents.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListEvents.kt similarity index 73% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListEvents.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListEvents.kt index 7bf58aba7a..f4ba30844a 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListEvents.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListEvents.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,11 @@ * limitations under the License. */ -package io.element.android.features.invite.impl +package io.element.android.features.invite.impl.invitelist import io.element.android.features.invite.impl.model.InviteListInviteSummary sealed interface InviteListEvents { data class AcceptInvite(val invite: InviteListInviteSummary) : InviteListEvents data class DeclineInvite(val invite: InviteListInviteSummary) : InviteListEvents - - data object ConfirmDeclineInvite : InviteListEvents - data object CancelDeclineInvite : InviteListEvents - - data object DismissAcceptError : InviteListEvents - data object DismissDeclineError : InviteListEvents } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListNode.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListNode.kt similarity index 93% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListNode.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListNode.kt index 1f3236e916..53c5b31095 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListNode.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListNode.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invite.impl +package io.element.android.features.invite.impl.invitelist import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -50,6 +50,7 @@ class InviteListNode @AssistedInject constructor( state = state, onBackClicked = ::onBackClicked, onInviteAccepted = ::onInviteAccepted, + onInviteDeclined = {} ) } } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListPresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt similarity index 56% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListPresenter.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt index f616450d25..a46f135aa3 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListPresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,43 +14,35 @@ * limitations under the License. */ -package io.element.android.features.invite.impl +package io.element.android.features.invite.impl.invitelist import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.MutableState import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import im.vector.app.features.analytics.plan.JoinedRoom import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.invite.impl.model.InviteListInviteSummary import io.element.android.features.invite.impl.model.InviteSender -import io.element.android.libraries.architecture.AsyncData +import io.element.android.features.invite.impl.response.AcceptDeclineInviteEvents +import io.element.android.features.invite.impl.response.AcceptDeclineInvitePresenter +import io.element.android.features.invite.impl.response.InviteData import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.roomlist.RoomSummary -import io.element.android.libraries.push.api.notifications.NotificationDrawerManager -import io.element.android.services.analytics.api.AnalyticsService -import io.element.android.services.analytics.api.extensions.toAnalyticsJoinedRoom import kotlinx.collections.immutable.toPersistentList -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.first -import kotlinx.coroutines.launch import javax.inject.Inject class InviteListPresenter @Inject constructor( private val client: MatrixClient, private val store: SeenInvitesStore, - private val analyticsService: AnalyticsService, - private val notificationDrawerManager: NotificationDrawerManager, + private val acceptDeclineInvitePresenter: AcceptDeclineInvitePresenter, ) : Presenter { @Composable override fun present(): InviteListState { @@ -75,40 +67,20 @@ class InviteListPresenter @Inject constructor( ) } - val localCoroutineScope = rememberCoroutineScope() - val acceptedAction: MutableState> = remember { mutableStateOf(AsyncData.Uninitialized) } - val declinedAction: MutableState> = remember { mutableStateOf(AsyncData.Uninitialized) } - val decliningInvite: MutableState = remember { mutableStateOf(null) } + val acceptDeclineInviteState = acceptDeclineInvitePresenter.present() fun handleEvent(event: InviteListEvents) { when (event) { is InviteListEvents.AcceptInvite -> { - acceptedAction.value = AsyncData.Uninitialized - localCoroutineScope.acceptInvite(event.invite.roomId, acceptedAction) + acceptDeclineInviteState.eventSink( + AcceptDeclineInviteEvents.AcceptInvite(event.invite.toInviteData()) + ) } is InviteListEvents.DeclineInvite -> { - decliningInvite.value = event.invite - } - - is InviteListEvents.ConfirmDeclineInvite -> { - declinedAction.value = AsyncData.Uninitialized - decliningInvite.value?.let { - localCoroutineScope.declineInvite(it.roomId, declinedAction) - } - decliningInvite.value = null - } - - is InviteListEvents.CancelDeclineInvite -> { - decliningInvite.value = null - } - - is InviteListEvents.DismissAcceptError -> { - acceptedAction.value = AsyncData.Uninitialized - } - - is InviteListEvents.DismissDeclineError -> { - declinedAction.value = AsyncData.Uninitialized + acceptDeclineInviteState.eventSink( + AcceptDeclineInviteEvents.DeclineInvite(event.invite.toInviteData()) + ) } } } @@ -124,38 +96,11 @@ class InviteListPresenter @Inject constructor( return InviteListState( inviteList = inviteList, - declineConfirmationDialog = decliningInvite.value?.let { - InviteDeclineConfirmationDialog.Visible( - isDirect = it.isDirect, - name = it.roomName, - ) - } ?: InviteDeclineConfirmationDialog.Hidden, - acceptedAction = acceptedAction.value, - declinedAction = declinedAction.value, + acceptDeclineInviteState = acceptDeclineInviteState, eventSink = ::handleEvent ) } - private fun CoroutineScope.acceptInvite(roomId: RoomId, acceptedAction: MutableState>) = launch { - suspend { - client.getRoom(roomId)?.use { - it.join().getOrThrow() - notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId, doRender = true) - analyticsService.capture(it.toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite)) - } - roomId - }.runCatchingUpdatingState(acceptedAction) - } - - private fun CoroutineScope.declineInvite(roomId: RoomId, declinedAction: MutableState>) = launch { - suspend { - client.getRoom(roomId)?.use { - it.leave().getOrThrow() - notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId, doRender = true) - }.let { } - }.runCatchingUpdatingState(declinedAction) - } - private fun RoomSummary.Filled.toInviteSummary(seen: Boolean) = details.run { val i = inviter val avatarData = if (isDirect && i != null) { @@ -203,4 +148,10 @@ class InviteListPresenter @Inject constructor( }, ) } + + private fun InviteListInviteSummary.toInviteData() = InviteData( + roomId = roomId, + roomName = roomName, + isDirect = isDirect, + ) } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListState.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListState.kt similarity index 61% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListState.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListState.kt index 42d73de547..60d8778c33 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListState.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListState.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,24 +14,16 @@ * limitations under the License. */ -package io.element.android.features.invite.impl +package io.element.android.features.invite.impl.invitelist import androidx.compose.runtime.Immutable +import io.element.android.features.invite.impl.response.AcceptDeclineInviteState import io.element.android.features.invite.impl.model.InviteListInviteSummary -import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.matrix.api.core.RoomId import kotlinx.collections.immutable.ImmutableList @Immutable data class InviteListState( val inviteList: ImmutableList, - val declineConfirmationDialog: InviteDeclineConfirmationDialog, - val acceptedAction: AsyncData, - val declinedAction: AsyncData, + val acceptDeclineInviteState: AcceptDeclineInviteState, val eventSink: (InviteListEvents) -> Unit ) - -sealed interface InviteDeclineConfirmationDialog { - data object Hidden : InviteDeclineConfirmationDialog - data class Visible(val isDirect: Boolean, val name: String) : InviteDeclineConfirmationDialog -} diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListStateProvider.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt similarity index 64% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListStateProvider.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt index 5f1d5dcc0f..11902e4673 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListStateProvider.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,35 +14,40 @@ * limitations under the License. */ -package io.element.android.features.invite.impl +package io.element.android.features.invite.impl.invitelist import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.invite.impl.model.InviteListInviteSummary import io.element.android.features.invite.impl.model.InviteSender -import io.element.android.libraries.architecture.AsyncData +import io.element.android.features.invite.impl.response.AcceptDeclineInviteState +import io.element.android.features.invite.impl.response.AcceptDeclineInviteStateProvider +import io.element.android.features.invite.impl.response.anAcceptDeclineInviteState import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf open class InviteListStateProvider : PreviewParameterProvider { + + private val acceptDeclineInviteStateProvider = AcceptDeclineInviteStateProvider() + override val values: Sequence get() = sequenceOf( - aInviteListState(), - aInviteListState().copy(inviteList = persistentListOf()), - aInviteListState().copy(declineConfirmationDialog = InviteDeclineConfirmationDialog.Visible(true, "Alice")), - aInviteListState().copy(declineConfirmationDialog = InviteDeclineConfirmationDialog.Visible(false, "Some Room")), - aInviteListState().copy(acceptedAction = AsyncData.Failure(Throwable("Whoops"))), - aInviteListState().copy(declinedAction = AsyncData.Failure(Throwable("Whoops"))), - ) + anInviteListState(), + anInviteListState(inviteList = persistentListOf()), + ) + acceptDeclineInviteStateProvider.values.map { acceptDeclineInviteState -> + anInviteListState(acceptDeclineInviteState = acceptDeclineInviteState) + } } -internal fun aInviteListState() = InviteListState( - inviteList = aInviteListInviteSummaryList(), - declineConfirmationDialog = InviteDeclineConfirmationDialog.Hidden, - acceptedAction = AsyncData.Uninitialized, - declinedAction = AsyncData.Uninitialized, - eventSink = {}, +internal fun anInviteListState( + inviteList: ImmutableList = aInviteListInviteSummaryList(), + acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(), + eventSink: (InviteListEvents) -> Unit = {} +) = InviteListState( + inviteList = inviteList, + acceptDeclineInviteState = acceptDeclineInviteState, + eventSink = eventSink, ) internal fun aInviteListInviteSummaryList(): ImmutableList { diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListView.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListView.kt similarity index 65% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListView.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListView.kt index 34da18f02f..2ad75e43eb 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/InviteListView.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListView.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 New Vector Ltd + * Copyright (c) 2024 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invite.impl +package io.element.android.features.invite.impl.invitelist import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -27,20 +27,16 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme +import io.element.android.features.invite.impl.R import io.element.android.features.invite.impl.components.InviteSummaryRow -import io.element.android.libraries.architecture.AsyncData +import io.element.android.features.invite.impl.response.AcceptDeclineInviteView import io.element.android.libraries.designsystem.components.button.BackButton -import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog -import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.aliasScreenTitle @@ -56,61 +52,19 @@ fun InviteListView( state: InviteListState, onBackClicked: () -> Unit, onInviteAccepted: (RoomId) -> Unit, + onInviteDeclined: (RoomId) -> Unit, modifier: Modifier = Modifier, ) { - if (state.acceptedAction is AsyncData.Success) { - val latestOnInviteAccepted by rememberUpdatedState(onInviteAccepted) - LaunchedEffect(state.acceptedAction) { - latestOnInviteAccepted(state.acceptedAction.data) - } - } - InviteListContent( state = state, modifier = modifier, onBackClicked = onBackClicked, ) - - if (state.declineConfirmationDialog is InviteDeclineConfirmationDialog.Visible) { - val contentResource = if (state.declineConfirmationDialog.isDirect) { - R.string.screen_invites_decline_direct_chat_message - } else { - R.string.screen_invites_decline_chat_message - } - - val titleResource = if (state.declineConfirmationDialog.isDirect) { - R.string.screen_invites_decline_direct_chat_title - } else { - R.string.screen_invites_decline_chat_title - } - - ConfirmationDialog( - content = stringResource(contentResource, state.declineConfirmationDialog.name), - title = stringResource(titleResource), - submitText = stringResource(CommonStrings.action_decline), - cancelText = stringResource(CommonStrings.action_cancel), - onSubmitClicked = { state.eventSink(InviteListEvents.ConfirmDeclineInvite) }, - onDismiss = { state.eventSink(InviteListEvents.CancelDeclineInvite) } - ) - } - - if (state.acceptedAction is AsyncData.Failure) { - ErrorDialog( - content = stringResource(CommonStrings.error_unknown), - title = stringResource(CommonStrings.common_error), - submitText = stringResource(CommonStrings.action_ok), - onDismiss = { state.eventSink(InviteListEvents.DismissAcceptError) } - ) - } - - if (state.declinedAction is AsyncData.Failure) { - ErrorDialog( - content = stringResource(CommonStrings.error_unknown), - title = stringResource(CommonStrings.common_error), - submitText = stringResource(CommonStrings.action_ok), - onDismiss = { state.eventSink(InviteListEvents.DismissDeclineError) } - ) - } + AcceptDeclineInviteView( + state = state.acceptDeclineInviteState, + onInviteAccepted = onInviteAccepted, + onInviteDeclined = onInviteDeclined, + ) } @OptIn(ExperimentalMaterial3Api::class) @@ -138,8 +92,8 @@ private fun InviteListContent( content = { padding -> Column( modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) + .padding(padding) + .consumeWindowInsets(padding) ) { if (state.inviteList.isEmpty()) { Spacer(Modifier.size(80.dp)) @@ -181,5 +135,6 @@ internal fun InviteListViewPreview(@PreviewParameter(InviteListStateProvider::cl state = state, onBackClicked = {}, onInviteAccepted = {}, + onInviteDeclined = {}, ) } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteEvents.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteEvents.kt new file mode 100644 index 0000000000..17d60cca37 --- /dev/null +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteEvents.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.impl.response + +sealed interface AcceptDeclineInviteEvents { + data class AcceptInvite(val invite: InviteData) : AcceptDeclineInviteEvents + data class DeclineInvite(val invite: InviteData) : AcceptDeclineInviteEvents + data object ConfirmDeclineInvite : AcceptDeclineInviteEvents + data object CancelDeclineInvite : AcceptDeclineInviteEvents + data object DismissAcceptError : AcceptDeclineInviteEvents + data object DismissDeclineError : AcceptDeclineInviteEvents +} diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteNode.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteNode.kt new file mode 100644 index 0000000000..4718b38881 --- /dev/null +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteNode.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.impl.response + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.di.SessionScope + +@ContributesNode(SessionScope::class) +class AcceptDeclineInviteNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: AcceptDeclineInvitePresenter, +) : Node(buildContext, plugins = plugins) { + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + AcceptDeclineInviteView( + state = state, + onInviteAccepted = {}, + onInviteDeclined = {}, + modifier = modifier + ) + } +} diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt new file mode 100644 index 0000000000..38302377f1 --- /dev/null +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.impl.response + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import im.vector.app.features.analytics.plan.JoinedRoom +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.architecture.runCatchingUpdatingState +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.push.api.notifications.NotificationDrawerManager +import io.element.android.services.analytics.api.AnalyticsService +import io.element.android.services.analytics.api.extensions.toAnalyticsJoinedRoom +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import java.util.Optional +import javax.inject.Inject +import kotlin.jvm.optionals.getOrNull + +class AcceptDeclineInvitePresenter @Inject constructor( + private val client: MatrixClient, + private val analyticsService: AnalyticsService, + private val notificationDrawerManager: NotificationDrawerManager, +) : Presenter { + + @Composable + override fun present(): AcceptDeclineInviteState { + + val localCoroutineScope = rememberCoroutineScope() + val acceptedAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } + val declinedAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } + var currentInvite by remember { + mutableStateOf>(Optional.empty()) + } + + fun handleEvents(event: AcceptDeclineInviteEvents) { + when (event) { + is AcceptDeclineInviteEvents.AcceptInvite -> { + currentInvite = Optional.of(event.invite) + localCoroutineScope.acceptInvite(event.invite.roomId, acceptedAction) + } + + is AcceptDeclineInviteEvents.DeclineInvite -> { + currentInvite = Optional.of(event.invite) + declinedAction.value = AsyncAction.Confirming + } + + is AcceptDeclineInviteEvents.ConfirmDeclineInvite -> { + declinedAction.value = AsyncAction.Uninitialized + currentInvite.getOrNull()?.let { + localCoroutineScope.declineInvite(it.roomId, declinedAction) + } + currentInvite = Optional.empty() + } + + is AcceptDeclineInviteEvents.CancelDeclineInvite -> { + currentInvite = Optional.empty() + declinedAction.value = AsyncAction.Uninitialized + } + + is AcceptDeclineInviteEvents.DismissAcceptError -> { + acceptedAction.value = AsyncAction.Uninitialized + } + + is AcceptDeclineInviteEvents.DismissDeclineError -> { + declinedAction.value = AsyncAction.Uninitialized + } + } + } + + return AcceptDeclineInviteState( + invite = currentInvite, + acceptAction = acceptedAction.value, + declineAction = declinedAction.value, + eventSink = ::handleEvents + ) + } + + private fun CoroutineScope.acceptInvite(roomId: RoomId, acceptedAction: MutableState>) = launch { + suspend { + client.getRoom(roomId)?.use { + it.join().getOrThrow() + notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId, doRender = true) + analyticsService.capture(it.toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite)) + } + roomId + }.runCatchingUpdatingState(acceptedAction) + } + + private fun CoroutineScope.declineInvite(roomId: RoomId, declinedAction: MutableState>) = launch { + suspend { + client.getRoom(roomId)?.use { + it.leave().getOrThrow() + notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId, doRender = true) + } + roomId + }.runCatchingUpdatingState(declinedAction) + } +} diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteState.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteState.kt new file mode 100644 index 0000000000..11b960f57b --- /dev/null +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteState.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.impl.response + +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.core.RoomId +import java.util.Optional + +data class AcceptDeclineInviteState( + val invite: Optional, + val acceptAction: AsyncAction, + val declineAction: AsyncAction, + val eventSink: (AcceptDeclineInviteEvents) -> Unit +) + +data class InviteData( + val roomId: RoomId, + val roomName: String, + val isDirect: Boolean, +) diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteStateProvider.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteStateProvider.kt new file mode 100644 index 0000000000..710c8b7538 --- /dev/null +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteStateProvider.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.impl.response + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.core.RoomId +import java.util.Optional + +open class AcceptDeclineInviteStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + anAcceptDeclineInviteState(), + anAcceptDeclineInviteState( + invite = Optional.of( + InviteData(RoomId(""), isDirect = true, roomName = "Alice"), + ), + declineAction = AsyncAction.Confirming, + ), + anAcceptDeclineInviteState( + invite = Optional.of( + InviteData(RoomId(""), isDirect = false, roomName = "Some room"), + ), + declineAction = AsyncAction.Confirming, + ), + anAcceptDeclineInviteState( + acceptAction = AsyncAction.Failure(Throwable("Whoops")), + ), + anAcceptDeclineInviteState( + declineAction = AsyncAction.Failure(Throwable("Whoops")), + ), + ) +} + +fun anAcceptDeclineInviteState( + invite: Optional = Optional.empty(), + acceptAction: AsyncAction = AsyncAction.Uninitialized, + declineAction: AsyncAction = AsyncAction.Uninitialized, + eventSink: (AcceptDeclineInviteEvents) -> Unit = {} +) = AcceptDeclineInviteState( + invite = invite, + acceptAction = acceptAction, + declineAction = declineAction, + eventSink = eventSink, +) diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt new file mode 100644 index 0000000000..a214fed4a2 --- /dev/null +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.impl.response + +import androidx.compose.foundation.layout.Box +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.PreviewLightDark +import androidx.compose.ui.tooling.preview.PreviewParameter +import io.element.android.features.invite.impl.R +import io.element.android.libraries.designsystem.components.async.AsyncActionView +import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.ui.strings.CommonStrings +import kotlin.jvm.optionals.getOrNull + +@Composable +fun AcceptDeclineInviteView( + state: AcceptDeclineInviteState, + onInviteAccepted: (RoomId) -> Unit, + onInviteDeclined: (RoomId) -> Unit, + modifier: Modifier = Modifier, +) { + Box(modifier = modifier) { + AsyncActionView( + async = state.acceptAction, + onSuccess = onInviteAccepted, + onErrorDismiss = { + state.eventSink(AcceptDeclineInviteEvents.DismissAcceptError) + }, + ) + AsyncActionView( + async = state.declineAction, + onSuccess = onInviteDeclined, + onErrorDismiss = { + state.eventSink(AcceptDeclineInviteEvents.DismissDeclineError) + }, + confirmationDialog = { + val invite = state.invite.getOrNull() + if (invite != null) { + DeclineConfirmationDialog( + invite = invite, + onConfirmClicked = { + state.eventSink(AcceptDeclineInviteEvents.ConfirmDeclineInvite) + }, + onDismissClicked = { + state.eventSink(AcceptDeclineInviteEvents.CancelDeclineInvite) + } + ) + } + } + ) + } +} + +@Composable +private fun DeclineConfirmationDialog( + invite: InviteData, + onConfirmClicked: () -> Unit, + onDismissClicked: () -> Unit, + modifier: Modifier = Modifier +) { + val contentResource = if (invite.isDirect) { + R.string.screen_invites_decline_direct_chat_message + } else { + R.string.screen_invites_decline_chat_message + } + + val titleResource = if (invite.isDirect) { + R.string.screen_invites_decline_direct_chat_title + } else { + R.string.screen_invites_decline_chat_title + } + + ConfirmationDialog( + modifier = modifier, + content = stringResource(contentResource, invite.roomName), + title = stringResource(titleResource), + submitText = stringResource(CommonStrings.action_decline), + cancelText = stringResource(CommonStrings.action_cancel), + onSubmitClicked = onConfirmClicked, + onDismiss = onDismissClicked, + ) +} + +@PreviewLightDark +@Composable +internal fun AcceptDeclineInviteViewLightPreview(@PreviewParameter(AcceptDeclineInviteStateProvider::class) state: AcceptDeclineInviteState) = + ElementPreview { + AcceptDeclineInviteView( + state = state, + onInviteAccepted = {}, + onInviteDeclined = {}, + ) + } diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/InviteListPresenterTests.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/InviteListPresenterTests.kt index b9acd5eb0b..8e192e01ed 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/InviteListPresenterTests.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/InviteListPresenterTests.kt @@ -22,6 +22,9 @@ import app.cash.turbine.TurbineTestContext import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.invite.api.SeenInvitesStore +import io.element.android.features.invite.impl.invitelist.InviteListEvents +import io.element.android.features.invite.impl.invitelist.InviteListPresenter +import io.element.android.features.invite.impl.invitelist.InviteListState import io.element.android.features.invite.test.FakeSeenInvitesStore import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData From 6a255a1b10d52012bf4dad60e6c0f4590fb8a946 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 9 Apr 2024 14:16:17 +0200 Subject: [PATCH 09/52] Room navigation : reuse accept/decline presentation logic --- .../android/appnav/LoggedInFlowNode.kt | 4 +++ .../android/appnav/room/join/JoinRoomNode.kt | 8 +++++ .../appnav/room/join/JoinRoomPresenter.kt | 36 ++++++++++++------- .../android/appnav/room/join/JoinRoomState.kt | 8 ++--- .../appnav/room/join/JoinRoomStateProvider.kt | 7 ++-- .../appnav/room/join/di/JoinRoomModule.kt | 5 ++- features/invite/api/build.gradle.kts | 2 +- .../invite/api/InviteListEntryPoint.kt | 2 +- .../response/AcceptDeclineInviteEvents.kt | 8 ++--- .../response/AcceptDeclineInvitePresenter.kt | 21 +++++++++++ .../api}/response/AcceptDeclineInviteState.kt | 10 ++---- .../AcceptDeclineInviteStateProvider.kt | 2 +- .../api/response/AcceptDeclineInviteView.kt | 31 ++++++++++++++++ .../invite/api/response/InviteData.kt | 25 +++++++++++++ .../invite/impl/invitelist/InviteListNode.kt | 7 +++- .../impl/invitelist/InviteListPresenter.kt | 6 ++-- .../invite/impl/invitelist/InviteListState.kt | 2 +- .../invitelist/InviteListStateProvider.kt | 6 ++-- .../invite/impl/invitelist/InviteListView.kt | 8 +++++ .../impl/response/AcceptDeclineInviteView.kt | 11 +++--- .../DefaultAcceptDeclineInviteEvents.kt | 26 ++++++++++++++ ...=> DefaultAcceptDeclineInvitePresenter.kt} | 33 ++++++++++------- ...e.kt => DefaultAcceptDeclineInviteView.kt} | 31 ++++++++-------- 23 files changed, 220 insertions(+), 79 deletions(-) rename features/invite/{impl/src/main/kotlin/io/element/android/features/invite/impl => api/src/main/kotlin/io/element/android/features/invite/api}/response/AcceptDeclineInviteEvents.kt (68%) create mode 100644 features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInvitePresenter.kt rename features/invite/{impl/src/main/kotlin/io/element/android/features/invite/impl => api/src/main/kotlin/io/element/android/features/invite/api}/response/AcceptDeclineInviteState.kt (80%) rename features/invite/{impl/src/main/kotlin/io/element/android/features/invite/impl => api/src/main/kotlin/io/element/android/features/invite/api}/response/AcceptDeclineInviteStateProvider.kt (97%) create mode 100644 features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteView.kt create mode 100644 features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/InviteData.kt create mode 100644 features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteEvents.kt rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/{AcceptDeclineInvitePresenter.kt => DefaultAcceptDeclineInvitePresenter.kt} (78%) rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/{AcceptDeclineInviteNode.kt => DefaultAcceptDeclineInviteView.kt} (56%) 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 8ba98e5a6b..4b82cb6992 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -350,6 +350,10 @@ class LoggedInFlowNode @AssistedInject constructor( backstack.pop() } + override fun onInviteClicked(roomId: RoomId) { + backstack.push(NavTarget.Room(roomId)) + } + override fun onInviteAccepted(roomId: RoomId) { backstack.push(NavTarget.Room(roomId)) } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt index cccc66ddfb..3574b37e2d 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt @@ -24,6 +24,7 @@ import com.bumble.appyx.core.plugin.Plugin import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.invite.api.response.AcceptDeclineInviteView import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.inputs import io.element.android.libraries.di.SessionScope @@ -34,6 +35,7 @@ class JoinRoomNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, presenterFactory: JoinRoomPresenter.Factory, + private val acceptDeclineInviteView: AcceptDeclineInviteView, ) : Node(buildContext, plugins = plugins) { data class Inputs( @@ -51,5 +53,11 @@ class JoinRoomNode @AssistedInject constructor( onBackPressed = ::navigateUp, modifier = modifier ) + acceptDeclineInviteView.Render( + state = state.acceptDeclineInviteState, + onInviteAccepted = {}, + onInviteDeclined = { navigateUp() }, + modifier = Modifier + ) } } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt index d80fb99b3e..60a59652bf 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt @@ -20,16 +20,17 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.produceState -import androidx.compose.runtime.rememberCoroutineScope import dagger.assisted.Assisted import dagger.assisted.AssistedInject +import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents +import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter +import io.element.android.features.invite.api.response.InviteData import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.roomlist.RoomListService -import kotlinx.coroutines.launch import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -37,6 +38,7 @@ class JoinRoomPresenter @AssistedInject constructor( @Assisted private val roomId: RoomId, private val matrixClient: MatrixClient, private val roomListService: RoomListService, + private val acceptDeclineInvitePresenter: AcceptDeclineInvitePresenter, ) : Presenter { interface Factory { @@ -47,6 +49,7 @@ class JoinRoomPresenter @AssistedInject constructor( override fun present(): JoinRoomState { val userMembership by roomListService.getUserMembershipForRoom(roomId).collectAsState(initial = Optional.empty()) val joinAuthorisationStatus = joinAuthorisationStatus(userMembership) + val acceptDeclineInviteState = acceptDeclineInvitePresenter.present() val roomInfo by produceState>(initialValue = AsyncData.Uninitialized, key1 = userMembership) { value = when { userMembership.isPresent -> { @@ -56,6 +59,7 @@ class JoinRoomPresenter @AssistedInject constructor( roomName = it.displayName, roomAlias = it.alias, memberCount = it.activeMemberCount, + isDirect = it.isDirect, roomAvatarUrl = it.avatarUrl ) } @@ -65,21 +69,17 @@ class JoinRoomPresenter @AssistedInject constructor( } } - val coroutineScope = rememberCoroutineScope() - fun handleEvents(event: JoinRoomEvents) { when (event) { JoinRoomEvents.AcceptInvite, JoinRoomEvents.JoinRoom -> { - coroutineScope.launch { - matrixClient.joinRoom(roomId) - } + acceptDeclineInviteState.eventSink( + AcceptDeclineInviteEvents.AcceptInvite(roomInfo.toInviteData()) + ) } JoinRoomEvents.DeclineInvite -> { - coroutineScope.launch { - matrixClient.getRoom(roomId)?.use { - it.leave() - } - } + acceptDeclineInviteState.eventSink( + AcceptDeclineInviteEvents.DeclineInvite(roomInfo.toInviteData()) + ) } } } @@ -87,11 +87,21 @@ class JoinRoomPresenter @AssistedInject constructor( return JoinRoomState( roomInfo = roomInfo, joinAuthorisationStatus = joinAuthorisationStatus, - currentAction = CurrentAction.None, + acceptDeclineInviteState = acceptDeclineInviteState, eventSink = ::handleEvents ) } + private fun AsyncData.toInviteData(): InviteData { + return dataOrNull().let { + InviteData( + roomId = roomId, + roomName = it?.roomName ?: "", + isDirect = it?.isDirect ?: false + ) + } + } + @Composable private fun joinAuthorisationStatus(userMembership: Optional): JoinAuthorisationStatus { return when { diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt index 2e95987d97..ca9f71baba 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt @@ -17,6 +17,7 @@ package io.element.android.appnav.room.join import androidx.compose.runtime.Immutable +import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -26,7 +27,7 @@ import io.element.android.libraries.matrix.api.core.RoomId data class JoinRoomState( val roomInfo: AsyncData, val joinAuthorisationStatus: JoinAuthorisationStatus, - val currentAction: CurrentAction, + val acceptDeclineInviteState: AcceptDeclineInviteState, val eventSink: (JoinRoomEvents) -> Unit ){ val showMemberCount = roomInfo.dataOrNull()?.memberCount != null @@ -37,6 +38,7 @@ data class RoomInfo( val roomName: String, val roomAlias: String?, val memberCount: Long?, + val isDirect: Boolean, val roomAvatarUrl: String?, ) { fun avatarData(size: AvatarSize): AvatarData { @@ -55,7 +57,3 @@ enum class JoinAuthorisationStatus { CanJoin, Unknown, } - -sealed interface CurrentAction { - data object None : CurrentAction -} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt index 928edb4ce4..6ac24cbdcb 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt @@ -17,6 +17,8 @@ package io.element.android.appnav.room.join import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.invite.api.response.AcceptDeclineInviteState +import io.element.android.features.invite.api.response.anAcceptDeclineInviteState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.RoomId @@ -45,16 +47,17 @@ fun aJoinRoomState( roomName = "Element x android", roomAlias = "#exa:matrix.org", memberCount = null, + isDirect = false, roomAvatarUrl = null ) ), joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown, - currentAction: CurrentAction = CurrentAction.None, + acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(), eventSink: (JoinRoomEvents) -> Unit = {} ) = JoinRoomState( roomInfo = roomInfo, joinAuthorisationStatus = joinAuthorisationStatus, - currentAction = currentAction, + acceptDeclineInviteState = acceptDeclineInviteState, eventSink = eventSink ) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt index fa7635a312..15b7f72ef0 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt @@ -20,6 +20,7 @@ import com.squareup.anvil.annotations.ContributesTo import dagger.Module import dagger.Provides import io.element.android.appnav.room.join.JoinRoomPresenter +import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -32,13 +33,15 @@ object JoinRoomModule { fun providesJoinRoomPresenterFactory( roomListService: RoomListService, client: MatrixClient, + acceptDeclineInvitePresenter: AcceptDeclineInvitePresenter, ): JoinRoomPresenter.Factory { return object : JoinRoomPresenter.Factory { override fun create(roomId: RoomId): JoinRoomPresenter { return JoinRoomPresenter( roomId = roomId, matrixClient = client, - roomListService = roomListService + roomListService = roomListService, + acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, ) } } diff --git a/features/invite/api/build.gradle.kts b/features/invite/api/build.gradle.kts index 1781ee93ae..52df82e38a 100644 --- a/features/invite/api/build.gradle.kts +++ b/features/invite/api/build.gradle.kts @@ -15,7 +15,7 @@ */ plugins { - id("io.element.android-library") + id("io.element.android-compose-library") } android { diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteListEntryPoint.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteListEntryPoint.kt index 6abfe8f518..c5063cdbc8 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteListEntryPoint.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteListEntryPoint.kt @@ -32,7 +32,7 @@ interface InviteListEntryPoint : FeatureEntryPoint { interface Callback : Plugin { fun onBackClicked() - + fun onInviteClicked(roomId: RoomId) fun onInviteAccepted(roomId: RoomId) } } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteEvents.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteEvents.kt similarity index 68% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteEvents.kt rename to features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteEvents.kt index 17d60cca37..8365ba3a90 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteEvents.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteEvents.kt @@ -14,13 +14,9 @@ * limitations under the License. */ -package io.element.android.features.invite.impl.response +package io.element.android.features.invite.api.response -sealed interface AcceptDeclineInviteEvents { +interface AcceptDeclineInviteEvents { data class AcceptInvite(val invite: InviteData) : AcceptDeclineInviteEvents data class DeclineInvite(val invite: InviteData) : AcceptDeclineInviteEvents - data object ConfirmDeclineInvite : AcceptDeclineInviteEvents - data object CancelDeclineInvite : AcceptDeclineInviteEvents - data object DismissAcceptError : AcceptDeclineInviteEvents - data object DismissDeclineError : AcceptDeclineInviteEvents } diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInvitePresenter.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInvitePresenter.kt new file mode 100644 index 0000000000..7ca0158c2b --- /dev/null +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInvitePresenter.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.api.response + +import io.element.android.libraries.architecture.Presenter + +interface AcceptDeclineInvitePresenter: Presenter diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteState.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteState.kt similarity index 80% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteState.kt rename to features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteState.kt index 11b960f57b..95980f0ac3 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteState.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invite.impl.response +package io.element.android.features.invite.api.response import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.RoomId @@ -24,11 +24,5 @@ data class AcceptDeclineInviteState( val invite: Optional, val acceptAction: AsyncAction, val declineAction: AsyncAction, - val eventSink: (AcceptDeclineInviteEvents) -> Unit -) - -data class InviteData( - val roomId: RoomId, - val roomName: String, - val isDirect: Boolean, + val eventSink: (AcceptDeclineInviteEvents) -> Unit, ) diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteStateProvider.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteStateProvider.kt similarity index 97% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteStateProvider.kt rename to features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteStateProvider.kt index 710c8b7538..e6a20d9b80 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteStateProvider.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteStateProvider.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invite.impl.response +package io.element.android.features.invite.api.response import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.architecture.AsyncAction diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteView.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteView.kt new file mode 100644 index 0000000000..c969458122 --- /dev/null +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteView.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.api.response + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import io.element.android.libraries.matrix.api.core.RoomId + +interface AcceptDeclineInviteView { + @Composable + fun Render( + state: AcceptDeclineInviteState, + onInviteAccepted: (RoomId) -> Unit, + onInviteDeclined: (RoomId) -> Unit, + modifier: Modifier, + ) +} diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/InviteData.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/InviteData.kt new file mode 100644 index 0000000000..081da0bfc6 --- /dev/null +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/InviteData.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.api.response + +import io.element.android.libraries.matrix.api.core.RoomId + +data class InviteData( + val roomId: RoomId, + val roomName: String, + val isDirect: Boolean, +) diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListNode.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListNode.kt index 53c5b31095..fe491b157e 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListNode.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListNode.kt @@ -43,6 +43,10 @@ class InviteListNode @AssistedInject constructor( plugins().forEach { it.onInviteAccepted(roomId) } } + private fun onInviteClicked(roomId: RoomId) { + plugins().forEach { it.onInviteClicked(roomId) } + } + @Composable override fun View(modifier: Modifier) { val state = presenter.present() @@ -50,7 +54,8 @@ class InviteListNode @AssistedInject constructor( state = state, onBackClicked = ::onBackClicked, onInviteAccepted = ::onInviteAccepted, - onInviteDeclined = {} + onInviteDeclined = {}, + onInviteClicked = ::onInviteClicked, ) } } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt index a46f135aa3..971e255898 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt @@ -24,11 +24,11 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import io.element.android.features.invite.api.SeenInvitesStore +import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents +import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter +import io.element.android.features.invite.api.response.InviteData import io.element.android.features.invite.impl.model.InviteListInviteSummary import io.element.android.features.invite.impl.model.InviteSender -import io.element.android.features.invite.impl.response.AcceptDeclineInviteEvents -import io.element.android.features.invite.impl.response.AcceptDeclineInvitePresenter -import io.element.android.features.invite.impl.response.InviteData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListState.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListState.kt index 60d8778c33..8a3cd69923 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListState.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListState.kt @@ -17,7 +17,7 @@ package io.element.android.features.invite.impl.invitelist import androidx.compose.runtime.Immutable -import io.element.android.features.invite.impl.response.AcceptDeclineInviteState +import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.impl.model.InviteListInviteSummary import kotlinx.collections.immutable.ImmutableList diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt index 11902e4673..e796896745 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt @@ -17,11 +17,11 @@ package io.element.android.features.invite.impl.invitelist import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.impl.model.InviteListInviteSummary import io.element.android.features.invite.impl.model.InviteSender -import io.element.android.features.invite.impl.response.AcceptDeclineInviteState -import io.element.android.features.invite.impl.response.AcceptDeclineInviteStateProvider -import io.element.android.features.invite.impl.response.anAcceptDeclineInviteState +import io.element.android.features.invite.api.response.AcceptDeclineInviteStateProvider +import io.element.android.features.invite.api.response.anAcceptDeclineInviteState import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import kotlinx.collections.immutable.ImmutableList diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListView.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListView.kt index 2ad75e43eb..16031d558c 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListView.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListView.kt @@ -16,6 +16,7 @@ package io.element.android.features.invite.impl.invitelist +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets @@ -53,11 +54,13 @@ fun InviteListView( onBackClicked: () -> Unit, onInviteAccepted: (RoomId) -> Unit, onInviteDeclined: (RoomId) -> Unit, + onInviteClicked: (RoomId) -> Unit, modifier: Modifier = Modifier, ) { InviteListContent( state = state, modifier = modifier, + onInviteClicked = onInviteClicked, onBackClicked = onBackClicked, ) AcceptDeclineInviteView( @@ -72,6 +75,7 @@ fun InviteListView( private fun InviteListContent( state: InviteListState, onBackClicked: () -> Unit, + onInviteClicked: (RoomId) -> Unit, modifier: Modifier = Modifier, ) { Scaffold( @@ -112,6 +116,9 @@ private fun InviteListContent( items = state.inviteList, ) { index, invite -> InviteSummaryRow( + modifier = Modifier.clickable( + onClick = { onInviteClicked(invite.roomId) } + ), invite = invite, onAcceptClicked = { state.eventSink(InviteListEvents.AcceptInvite(invite)) }, onDeclineClicked = { state.eventSink(InviteListEvents.DeclineInvite(invite)) }, @@ -136,5 +143,6 @@ internal fun InviteListViewPreview(@PreviewParameter(InviteListStateProvider::cl onBackClicked = {}, onInviteAccepted = {}, onInviteDeclined = {}, + onInviteClicked = {}, ) } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt index a214fed4a2..f1462e8dba 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt @@ -22,6 +22,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewParameter +import io.element.android.features.invite.api.response.AcceptDeclineInviteState +import io.element.android.features.invite.api.response.AcceptDeclineInviteStateProvider +import io.element.android.features.invite.api.response.InviteData import io.element.android.features.invite.impl.R import io.element.android.libraries.designsystem.components.async.AsyncActionView import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog @@ -42,14 +45,14 @@ fun AcceptDeclineInviteView( async = state.acceptAction, onSuccess = onInviteAccepted, onErrorDismiss = { - state.eventSink(AcceptDeclineInviteEvents.DismissAcceptError) + state.eventSink(DefaultAcceptDeclineInviteEvents.DismissAcceptError) }, ) AsyncActionView( async = state.declineAction, onSuccess = onInviteDeclined, onErrorDismiss = { - state.eventSink(AcceptDeclineInviteEvents.DismissDeclineError) + state.eventSink(DefaultAcceptDeclineInviteEvents.DismissDeclineError) }, confirmationDialog = { val invite = state.invite.getOrNull() @@ -57,10 +60,10 @@ fun AcceptDeclineInviteView( DeclineConfirmationDialog( invite = invite, onConfirmClicked = { - state.eventSink(AcceptDeclineInviteEvents.ConfirmDeclineInvite) + state.eventSink(DefaultAcceptDeclineInviteEvents.ConfirmDeclineInvite) }, onDismissClicked = { - state.eventSink(AcceptDeclineInviteEvents.CancelDeclineInvite) + state.eventSink(DefaultAcceptDeclineInviteEvents.CancelDeclineInvite) } ) } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteEvents.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteEvents.kt new file mode 100644 index 0000000000..4698b1ba2d --- /dev/null +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteEvents.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.impl.response + +import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents + +sealed interface DefaultAcceptDeclineInviteEvents: AcceptDeclineInviteEvents { + data object ConfirmDeclineInvite : DefaultAcceptDeclineInviteEvents + data object CancelDeclineInvite : DefaultAcceptDeclineInviteEvents + data object DismissAcceptError : DefaultAcceptDeclineInviteEvents + data object DismissDeclineError : DefaultAcceptDeclineInviteEvents +} diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInvitePresenter.kt similarity index 78% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInvitePresenter.kt index 38302377f1..ccdcf1e27a 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInvitePresenter.kt @@ -23,10 +23,16 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue +import com.squareup.anvil.annotations.ContributesBinding import im.vector.app.features.analytics.plan.JoinedRoom +import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents +import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter +import io.element.android.features.invite.api.response.AcceptDeclineInviteState +import io.element.android.features.invite.api.response.InviteData import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState +import io.element.android.libraries.architecture.runUpdatingState +import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.push.api.notifications.NotificationDrawerManager @@ -38,11 +44,12 @@ import java.util.Optional import javax.inject.Inject import kotlin.jvm.optionals.getOrNull -class AcceptDeclineInvitePresenter @Inject constructor( +@ContributesBinding(SessionScope::class) +class DefaultAcceptDeclineInvitePresenter @Inject constructor( private val client: MatrixClient, private val analyticsService: AnalyticsService, private val notificationDrawerManager: NotificationDrawerManager, -) : Presenter { +) : AcceptDeclineInvitePresenter { @Composable override fun present(): AcceptDeclineInviteState { @@ -66,7 +73,7 @@ class AcceptDeclineInvitePresenter @Inject constructor( declinedAction.value = AsyncAction.Confirming } - is AcceptDeclineInviteEvents.ConfirmDeclineInvite -> { + is DefaultAcceptDeclineInviteEvents.ConfirmDeclineInvite -> { declinedAction.value = AsyncAction.Uninitialized currentInvite.getOrNull()?.let { localCoroutineScope.declineInvite(it.roomId, declinedAction) @@ -74,16 +81,16 @@ class AcceptDeclineInvitePresenter @Inject constructor( currentInvite = Optional.empty() } - is AcceptDeclineInviteEvents.CancelDeclineInvite -> { + is DefaultAcceptDeclineInviteEvents.CancelDeclineInvite -> { currentInvite = Optional.empty() declinedAction.value = AsyncAction.Uninitialized } - is AcceptDeclineInviteEvents.DismissAcceptError -> { + is DefaultAcceptDeclineInviteEvents.DismissAcceptError -> { acceptedAction.value = AsyncAction.Uninitialized } - is AcceptDeclineInviteEvents.DismissDeclineError -> { + is DefaultAcceptDeclineInviteEvents.DismissDeclineError -> { declinedAction.value = AsyncAction.Uninitialized } } @@ -98,14 +105,14 @@ class AcceptDeclineInvitePresenter @Inject constructor( } private fun CoroutineScope.acceptInvite(roomId: RoomId, acceptedAction: MutableState>) = launch { - suspend { - client.getRoom(roomId)?.use { - it.join().getOrThrow() + acceptedAction.runUpdatingState { + client.joinRoom(roomId).onSuccess { notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId, doRender = true) - analyticsService.capture(it.toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite)) + client.getRoom(roomId)?.use { room -> + analyticsService.capture(room.toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite)) + } } - roomId - }.runCatchingUpdatingState(acceptedAction) + } } private fun CoroutineScope.declineInvite(roomId: RoomId, declinedAction: MutableState>) = launch { diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteNode.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteView.kt similarity index 56% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteNode.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteView.kt index 4718b38881..b87f5fa655 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteNode.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteView.kt @@ -18,28 +18,27 @@ package io.element.android.features.invite.impl.response import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.bumble.appyx.core.modality.BuildContext -import com.bumble.appyx.core.node.Node -import com.bumble.appyx.core.plugin.Plugin -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject -import io.element.android.anvilannotations.ContributesNode +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.invite.api.response.AcceptDeclineInviteState +import io.element.android.features.invite.api.response.AcceptDeclineInviteView import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.RoomId +import javax.inject.Inject -@ContributesNode(SessionScope::class) -class AcceptDeclineInviteNode @AssistedInject constructor( - @Assisted buildContext: BuildContext, - @Assisted plugins: List, - private val presenter: AcceptDeclineInvitePresenter, -) : Node(buildContext, plugins = plugins) { +@ContributesBinding(SessionScope::class) +class DefaultAcceptDeclineInviteView @Inject constructor() : AcceptDeclineInviteView { @Composable - override fun View(modifier: Modifier) { - val state = presenter.present() + override fun Render( + state: AcceptDeclineInviteState, + onInviteAccepted: (RoomId) -> Unit, + onInviteDeclined: (RoomId) -> Unit, + modifier: Modifier, + ) { AcceptDeclineInviteView( state = state, - onInviteAccepted = {}, - onInviteDeclined = {}, + onInviteAccepted = onInviteAccepted, + onInviteDeclined = onInviteDeclined, modifier = modifier ) } From 5e684edb8de388d43c29205efe3483bbb3323fe2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 9 Apr 2024 15:03:27 +0200 Subject: [PATCH 10/52] Room navigation : extract JoinRoomNode to his own feature module --- .../android/appnav/room/RoomFlowNode.kt | 8 +-- features/joinroom/api/build.gradle.kts | 28 ++++++++++ .../joinroom/api/JoinRoomEntryPoint.kt | 33 ++++++++++++ features/joinroom/impl/build.gradle.kts | 54 +++++++++++++++++++ .../impl/DefaultJoinRoomEntryPoint.kt | 36 +++++++++++++ .../features/joinroom/impl}/JoinRoomEvents.kt | 2 +- .../features/joinroom/impl}/JoinRoomNode.kt | 11 ++-- .../joinroom/impl}/JoinRoomPresenter.kt | 2 +- .../features/joinroom/impl}/JoinRoomState.kt | 2 +- .../joinroom/impl}/JoinRoomStateProvider.kt | 2 +- .../features/joinroom/impl}/JoinRoomView.kt | 2 +- .../joinroom/impl}/di/JoinRoomModule.kt | 4 +- 12 files changed, 165 insertions(+), 19 deletions(-) create mode 100644 features/joinroom/api/build.gradle.kts create mode 100644 features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt create mode 100644 features/joinroom/impl/build.gradle.kts create mode 100644 features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPoint.kt rename {appnav/src/main/kotlin/io/element/android/appnav/room/join => features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl}/JoinRoomEvents.kt (93%) rename {appnav/src/main/kotlin/io/element/android/appnav/room/join => features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl}/JoinRoomNode.kt (87%) rename {appnav/src/main/kotlin/io/element/android/appnav/room/join => features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl}/JoinRoomPresenter.kt (98%) rename {appnav/src/main/kotlin/io/element/android/appnav/room/join => features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl}/JoinRoomState.kt (97%) rename {appnav/src/main/kotlin/io/element/android/appnav/room/join => features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl}/JoinRoomStateProvider.kt (97%) rename {appnav/src/main/kotlin/io/element/android/appnav/room/join => features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl}/JoinRoomView.kt (99%) rename {appnav/src/main/kotlin/io/element/android/appnav/room/join => features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl}/di/JoinRoomModule.kt (93%) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt index beef8a883c..7149937e7e 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt @@ -34,16 +34,15 @@ import com.bumble.appyx.navmodel.backstack.operation.newRoot import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode -import io.element.android.appnav.room.join.JoinRoomNode import io.element.android.appnav.room.joined.JoinedRoomFlowNode import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode +import io.element.android.features.joinroom.api.JoinRoomEntryPoint import io.element.android.libraries.architecture.BackstackView import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.inputs import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator -import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership @@ -64,6 +63,7 @@ class RoomFlowNode @AssistedInject constructor( @Assisted plugins: List, private val roomListService: RoomListService, private val roomMembershipObserver: RoomMembershipObserver, + private val joinRoomEntryPoint: JoinRoomEntryPoint, ) : BaseFlowNode( backstack = BackStack( initialElement = NavTarget.Loading, @@ -118,8 +118,8 @@ class RoomFlowNode @AssistedInject constructor( return when (navTarget) { NavTarget.Loading -> loadingNode(buildContext) NavTarget.JoinRoom -> { - val inputs = JoinRoomNode.Inputs(inputs.roomId) - createNode(buildContext, plugins = listOf(inputs)) + val inputs = JoinRoomEntryPoint.Inputs(inputs.roomId) + joinRoomEntryPoint.createNode(this, buildContext, inputs) } NavTarget.JoinedRoom -> { val roomFlowNodeCallback = plugins() diff --git a/features/joinroom/api/build.gradle.kts b/features/joinroom/api/build.gradle.kts new file mode 100644 index 0000000000..697dc5deee --- /dev/null +++ b/features/joinroom/api/build.gradle.kts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.features.joinroom.api" +} + +dependencies { + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) +} diff --git a/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt b/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt new file mode 100644 index 0000000000..50dc1010d8 --- /dev/null +++ b/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.joinroom.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.NodeInputs +import io.element.android.libraries.matrix.api.core.RoomId + +interface JoinRoomEntryPoint : FeatureEntryPoint { + + fun createNode(parentNode: Node, buildContext: BuildContext, inputs: Inputs): Node + + data class Inputs( + val roomId: RoomId, + ) : NodeInputs +} + diff --git a/features/joinroom/impl/build.gradle.kts b/features/joinroom/impl/build.gradle.kts new file mode 100644 index 0000000000..047bc1d960 --- /dev/null +++ b/features/joinroom/impl/build.gradle.kts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Suppress("DSL_SCOPE_VIOLATION") +plugins { + id("io.element.android-compose-library") + alias(libs.plugins.anvil) + alias(libs.plugins.ksp) + id("kotlin-parcelize") +} + +android { + namespace = "io.element.android.features.joinroom.impl" +} + +anvil { + generateDaggerFactories.set(true) +} + +dependencies { + implementation(projects.anvilannotations) + anvil(projects.anvilcodegen) + api(projects.features.joinroom.api) + implementation(projects.libraries.core) + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) + implementation(projects.libraries.matrixui) + implementation(projects.libraries.designsystem) + implementation(projects.features.invite.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(projects.libraries.matrix.test) + + ksp(libs.showkase.processor) +} diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPoint.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPoint.kt new file mode 100644 index 0000000000..ab2745a63f --- /dev/null +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPoint.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.joinroom.impl + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.joinroom.api.JoinRoomEntryPoint +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class DefaultJoinRoomEntryPoint @Inject constructor() : JoinRoomEntryPoint { + + override fun createNode(parentNode: Node, buildContext: BuildContext, inputs: JoinRoomEntryPoint.Inputs): Node { + return parentNode.createNode( + buildContext = buildContext, + plugins = listOf(inputs) + ) + } +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomEvents.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt similarity index 93% rename from appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomEvents.kt rename to features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt index 7679e77c63..e3dc73f505 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomEvents.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.appnav.room.join +package io.element.android.features.joinroom.impl sealed interface JoinRoomEvents { data object JoinRoom: JoinRoomEvents diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt similarity index 87% rename from appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt rename to features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt index 3574b37e2d..a0dcf7a52c 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomNode.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.appnav.room.join +package io.element.android.features.joinroom.impl import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -25,10 +25,9 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.features.invite.api.response.AcceptDeclineInviteView -import io.element.android.libraries.architecture.NodeInputs +import io.element.android.features.joinroom.api.JoinRoomEntryPoint import io.element.android.libraries.architecture.inputs import io.element.android.libraries.di.SessionScope -import io.element.android.libraries.matrix.api.core.RoomId @ContributesNode(SessionScope::class) class JoinRoomNode @AssistedInject constructor( @@ -38,11 +37,7 @@ class JoinRoomNode @AssistedInject constructor( private val acceptDeclineInviteView: AcceptDeclineInviteView, ) : Node(buildContext, plugins = plugins) { - data class Inputs( - val roomId: RoomId, - ) : NodeInputs - - private val inputs: Inputs = inputs() + private val inputs: JoinRoomEntryPoint.Inputs = inputs() private val presenter = presenterFactory.create(inputs.roomId) @Composable diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt similarity index 98% rename from appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt rename to features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt index 60a59652bf..d74ec9d75b 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomPresenter.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.appnav.room.join +package io.element.android.features.joinroom.impl import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt similarity index 97% rename from appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt rename to features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt index ca9f71baba..2437a76b3e 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.appnav.room.join +package io.element.android.features.joinroom.impl import androidx.compose.runtime.Immutable import io.element.android.features.invite.api.response.AcceptDeclineInviteState diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt similarity index 97% rename from appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt rename to features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 6ac24cbdcb..063f8b1315 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.appnav.room.join +package io.element.android.features.joinroom.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.invite.api.response.AcceptDeclineInviteState diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt similarity index 99% rename from appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt rename to features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index eff9181c11..e803c8315c 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.appnav.room.join +package io.element.android.features.joinroom.impl import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt similarity index 93% rename from appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt rename to features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt index 15b7f72ef0..b4fc45ca18 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/join/di/JoinRoomModule.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package io.element.android.appnav.room.join.di +package io.element.android.features.joinroom.impl.di import com.squareup.anvil.annotations.ContributesTo import dagger.Module import dagger.Provides -import io.element.android.appnav.room.join.JoinRoomPresenter import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter +import io.element.android.features.joinroom.impl.JoinRoomPresenter import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId From 14a638626d136fd2b4afd928f1be3be211d17e31 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 9 Apr 2024 15:53:25 +0200 Subject: [PATCH 11/52] Room navigation : import join room strings --- .../android/features/joinroom/impl/JoinRoomView.kt | 4 ++-- features/joinroom/impl/src/main/res/values/localazy.xml | 9 +++++++++ tools/localazy/config.json | 6 ++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 features/joinroom/impl/src/main/res/values/localazy.xml diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index e803c8315c..a4a252a41e 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -147,14 +147,14 @@ private fun JoinRoomContent( } Spacer(modifier = Modifier.height(16.dp)) Text( - text = "Preview is not available", + text = stringResource(id = R.string.screen_join_room_title_no_preview), style = ElementTheme.typography.fontHeadingMdBold, textAlign = TextAlign.Center, color = ElementTheme.colors.textPrimary, ) Spacer(modifier = Modifier.height(8.dp)) Text( - text = "You must be a member of this room to view the message history.", + text = stringResource(id = R.string.screen_join_room_subtitle_no_preview), style = ElementTheme.typography.fontBodyMdRegular, textAlign = TextAlign.Center, color = ElementTheme.colors.textSecondary, diff --git a/features/joinroom/impl/src/main/res/values/localazy.xml b/features/joinroom/impl/src/main/res/values/localazy.xml new file mode 100644 index 0000000000..1c187d403d --- /dev/null +++ b/features/joinroom/impl/src/main/res/values/localazy.xml @@ -0,0 +1,9 @@ + + + "Join room" + "Knock to join" + "Click the button below and a room administrator will be notified. You’ll be able to join the conversation once approved." + "You must be a member of this room to view the message history." + "Want to join this room?" + "Preview is not available" + diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 35e13730c2..d005eeed7e 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -233,6 +233,12 @@ "includeRegex" : [ "screen_room_directory_.*" ] + }, + { + "name" : ":features:joinroom:impl", + "includeRegex" : [ + "screen_join_room_.*" + ] } ] } From a37b9320cef33fc9a5e28c2bad8d6dc15ab57cb7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:02:01 +0000 Subject: [PATCH 12/52] Update dependency androidx.media3:media3-exoplayer to v1.3.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8474ae9c43..dba712311b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ constraintlayout = "2.1.4" constraintlayout_compose = "1.0.1" lifecycle = "2.7.0" activity = "1.8.2" -media3 = "1.3.0" +media3 = "1.3.1" # Compose compose_bom = "2024.04.00" From 9604acb75a3897dbbba44a6ecd3285536d48930d Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 10 Apr 2024 11:41:06 +0200 Subject: [PATCH 13/52] Room navigation : more reliable roomInfoFlow method --- .../android/appnav/room/RoomFlowNode.kt | 24 +++++++-------- .../joinroom/impl/JoinRoomPresenter.kt | 29 ++++++++++--------- .../features/joinroom/impl/JoinRoomState.kt | 5 ++-- .../joinroom/impl/JoinRoomStateProvider.kt | 1 + .../features/joinroom/impl/JoinRoomView.kt | 6 +++- .../joinroom/impl/di/JoinRoomModule.kt | 1 - .../impl/datasource/RoomListDataSource.kt | 2 +- .../impl/search/RoomListSearchDataSource.kt | 2 +- .../libraries/matrix/api/MatrixClient.kt | 5 ++++ .../matrix/api/roomlist/DynamicRoomList.kt | 3 ++ .../matrix/api/roomlist/RoomListService.kt | 16 ++++------ .../libraries/matrix/impl/RustMatrixClient.kt | 22 ++++++++++++++ .../matrix/impl/roomlist/RoomListFactory.kt | 5 +++- .../impl/roomlist/RustRoomListService.kt | 28 ------------------ 14 files changed, 75 insertions(+), 74 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt index 7149937e7e..91809fe0ca 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt @@ -44,13 +44,11 @@ import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.inputs import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomMembershipObserver -import io.element.android.libraries.matrix.api.roomlist.RoomListService -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize @@ -61,7 +59,7 @@ import kotlin.jvm.optionals.getOrNull class RoomFlowNode @AssistedInject constructor( @Assisted val buildContext: BuildContext, @Assisted plugins: List, - private val roomListService: RoomListService, + private val client: MatrixClient, private val roomMembershipObserver: RoomMembershipObserver, private val joinRoomEntryPoint: JoinRoomEntryPoint, ) : BaseFlowNode( @@ -92,18 +90,16 @@ class RoomFlowNode @AssistedInject constructor( override fun onBuilt() { super.onBuilt() - roomListService.getUserMembershipForRoom( + client.getRoomInfoFlow( inputs.roomId - ).flowOn(Dispatchers.Default) - .onEach { membership -> - Timber.d("RoomMembership = $membership") - if (membership.getOrNull() == CurrentUserMembership.JOINED) { - backstack.newRoot(NavTarget.JoinedRoom) - } else { - backstack.newRoot(NavTarget.JoinRoom) - } + ).onEach { roomInfo -> + Timber.d("Room membership: ${roomInfo.map { it.currentUserMembership }}") + if (roomInfo.getOrNull()?.currentUserMembership == CurrentUserMembership.JOINED) { + backstack.newRoot(NavTarget.JoinedRoom) + } else { + backstack.newRoot(NavTarget.JoinRoom) } - .flowOn(Dispatchers.Main) + } .launchIn(lifecycleScope) roomMembershipObserver.updates 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 d74ec9d75b..39b8058075 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 @@ -30,14 +30,13 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership -import io.element.android.libraries.matrix.api.roomlist.RoomListService +import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import java.util.Optional import kotlin.jvm.optionals.getOrNull class JoinRoomPresenter @AssistedInject constructor( @Assisted private val roomId: RoomId, private val matrixClient: MatrixClient, - private val roomListService: RoomListService, private val acceptDeclineInvitePresenter: AcceptDeclineInvitePresenter, ) : Presenter { @@ -47,23 +46,24 @@ class JoinRoomPresenter @AssistedInject constructor( @Composable override fun present(): JoinRoomState { - val userMembership by roomListService.getUserMembershipForRoom(roomId).collectAsState(initial = Optional.empty()) - val joinAuthorisationStatus = joinAuthorisationStatus(userMembership) + val mxRoomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty()) + val joinAuthorisationStatus = joinAuthorisationStatus(mxRoomInfo) val acceptDeclineInviteState = acceptDeclineInvitePresenter.present() - val roomInfo by produceState>(initialValue = AsyncData.Uninitialized, key1 = userMembership) { + val roomInfo by produceState>(initialValue = AsyncData.Uninitialized, key1 = mxRoomInfo) { value = when { - userMembership.isPresent -> { - val roomInfo = matrixClient.getRoom(roomId)?.use { + mxRoomInfo.isPresent -> { + val roomInfo = mxRoomInfo.get().let { RoomInfo( - roomId = it.roomId, - roomName = it.displayName, - roomAlias = it.alias, - memberCount = it.activeMemberCount, + roomId = roomId, + roomName = it.name, + roomAlias = it.canonicalAlias, + memberCount = it.activeMembersCount, isDirect = it.isDirect, + topic = it.topic, roomAvatarUrl = it.avatarUrl ) } - roomInfo?.let { AsyncData.Success(it) } ?: AsyncData.Failure(Exception("Failed to load room info")) + AsyncData.Success(roomInfo) } else -> AsyncData.Uninitialized } @@ -103,9 +103,10 @@ class JoinRoomPresenter @AssistedInject constructor( } @Composable - private fun joinAuthorisationStatus(userMembership: Optional): JoinAuthorisationStatus { + private fun joinAuthorisationStatus(roomInfo: Optional): JoinAuthorisationStatus { + val userMembership = roomInfo.getOrNull()?.currentUserMembership return when { - userMembership.getOrNull() == CurrentUserMembership.INVITED -> return JoinAuthorisationStatus.IsInvited + userMembership == CurrentUserMembership.INVITED -> return JoinAuthorisationStatus.IsInvited else -> JoinAuthorisationStatus.Unknown } } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt index 2437a76b3e..b866ec0d42 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -29,15 +29,16 @@ data class JoinRoomState( val joinAuthorisationStatus: JoinAuthorisationStatus, val acceptDeclineInviteState: AcceptDeclineInviteState, val eventSink: (JoinRoomEvents) -> Unit -){ +) { val showMemberCount = roomInfo.dataOrNull()?.memberCount != null } data class RoomInfo( val roomId: RoomId, - val roomName: String, + val roomName: String?, val roomAlias: String?, val memberCount: Long?, + val topic: String?, val isDirect: Boolean, val roomAvatarUrl: String?, ) { diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 063f8b1315..7ae82b3ce9 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -48,6 +48,7 @@ fun aJoinRoomState( roomAlias = "#exa:matrix.org", memberCount = null, isDirect = false, + topic = null, roomAvatarUrl = null ) ), diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index a4a252a41e..d85ba33edf 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -203,7 +203,11 @@ private fun JoinRoomTopBar( when (asyncRoomInfo) { is AsyncData.Success -> { val roomInfo = asyncRoomInfo.data - RoomAvatarAndNameRow(roomName = roomInfo.roomName, roomAvatar = roomInfo.avatarData(AvatarSize.TimelineRoom)) + if(roomInfo.roomName == null){ + IconTitlePlaceholdersRowMolecule(iconSize = AvatarSize.TimelineRoom.dp) + }else { + RoomAvatarAndNameRow(roomName = roomInfo.roomName, roomAvatar = roomInfo.avatarData(AvatarSize.TimelineRoom)) + } } else -> { IconTitlePlaceholdersRowMolecule(iconSize = AvatarSize.TimelineRoom.dp) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt index b4fc45ca18..b1e9b04879 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt @@ -40,7 +40,6 @@ object JoinRoomModule { return JoinRoomPresenter( roomId = roomId, matrixClient = client, - roomListService = roomListService, acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, ) } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt index 2f078d7a69..e2508446e7 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt @@ -60,7 +60,7 @@ class RoomListDataSource @Inject constructor( fun launchIn(coroutineScope: CoroutineScope) { roomListService .allRooms - .summaries + .filteredSummaries .onEach { roomSummaries -> replaceWith(roomSummaries) } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchDataSource.kt index 59d8bf9f13..165c92bff8 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchDataSource.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchDataSource.kt @@ -45,7 +45,7 @@ class RoomListSearchDataSource @Inject constructor( source = RoomList.Source.All, ) - val roomSummaries: Flow> = roomList.summaries + val roomSummaries: Flow> = roomList.filteredSummaries .map { roomSummaries -> roomSummaries .filterIsInstance() 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 e6c536ee72..0875c54043 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 @@ -27,7 +27,9 @@ import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService +import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService import io.element.android.libraries.matrix.api.roomlist.RoomListService @@ -37,8 +39,10 @@ import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import java.io.Closeable +import java.util.Optional interface MatrixClient : Closeable { val sessionId: SessionId @@ -89,6 +93,7 @@ interface MatrixClient : Closeable { suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result suspend fun uploadMedia(mimeType: String, data: ByteArray, progressCallback: ProgressCallback?): Result fun roomMembershipObserver(): RoomMembershipObserver + fun getRoomInfoFlow(roomId: RoomId): Flow> fun isMe(userId: UserId?) = userId == sessionId } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/DynamicRoomList.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/DynamicRoomList.kt index 8cb43af24c..7bd4c42bdf 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/DynamicRoomList.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/DynamicRoomList.kt @@ -17,6 +17,7 @@ package io.element.android.libraries.matrix.api.roomlist import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn @@ -32,6 +33,8 @@ interface DynamicRoomList : RoomList { val loadedPages: StateFlow val pageSize: Int + val filteredSummaries: SharedFlow> + /** * Load more rooms into the list if possible. */ diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt index 4534f10a74..860aeb7e68 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt @@ -17,15 +17,9 @@ package io.element.android.libraries.matrix.api.roomlist import androidx.compose.runtime.Immutable -import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.room.CurrentUserMembership import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.map -import java.util.Optional +import kotlinx.coroutines.flow.filterIsInstance /** * Entry point for the room list api. @@ -86,10 +80,10 @@ interface RoomListService { */ val state: StateFlow - /** - * Get a flow of the room summary for a given room id. - */ - fun getUserMembershipForRoom(roomId: RoomId): Flow> +} + +fun RoomList.loadedStateFlow(): Flow { + return loadingState.filterIsInstance() } 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 546acc6e84..997301c2a8 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 @@ -35,6 +35,7 @@ import io.element.android.libraries.matrix.api.notificationsettings.Notification import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService import io.element.android.libraries.matrix.api.roomlist.RoomListService @@ -79,12 +80,15 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.buffer +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch @@ -104,8 +108,10 @@ import org.matrix.rustcomponents.sdk.TimelineEventTypeFilter import org.matrix.rustcomponents.sdk.use import timber.log.Timber import java.io.File +import java.util.Optional import java.util.concurrent.atomic.AtomicBoolean import kotlin.time.Duration +import kotlin.time.Duration.Companion.INFINITE import kotlin.time.Duration.Companion.seconds import org.matrix.rustcomponents.sdk.CreateRoomParameters as RustCreateRoomParameters import org.matrix.rustcomponents.sdk.RoomPreset as RustRoomPreset @@ -524,6 +530,22 @@ class RustMatrixClient( override fun roomMembershipObserver(): RoomMembershipObserver = roomMembershipObserver + override fun getRoomInfoFlow(roomId: RoomId): Flow> { + return flow { + var room = getRoom(roomId) + if (room == null) { + emit(Optional.empty()) + awaitRoom(roomId, INFINITE) + room = getRoom(roomId) + } + room?.use { + room.roomInfoFlow + .map { roomInfo -> Optional.of(roomInfo) } + .collect(this) + } + }.distinctUntilChanged() + } + private suspend fun File.getCacheSize( includeCryptoDb: Boolean = false, ): Long = withContext(sessionDispatcher) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt index 4231af07d2..7ac4aed637 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt @@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.roomlist.RoomSummary import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.getAndUpdate import kotlinx.coroutines.flow.launchIn @@ -92,7 +93,8 @@ internal class RoomListFactory( innerRoomList?.destroy() } return RustDynamicRoomList( - summaries = filteredSummariesFlow, + summaries = summariesFlow, + filteredSummaries = filteredSummariesFlow, loadingState = loadingStateFlow, currentFilter = currentFilter, loadedPages = loadedPages, @@ -105,6 +107,7 @@ internal class RoomListFactory( private class RustDynamicRoomList( override val summaries: MutableSharedFlow>, + override val filteredSummaries: SharedFlow>, override val loadingState: MutableStateFlow, override val currentFilter: MutableStateFlow, override val loadedPages: MutableStateFlow, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt index 09e0a514b1..70310e472e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt @@ -16,24 +16,16 @@ package io.element.android.libraries.matrix.impl.roomlist -import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.roomlist.DynamicRoomList import io.element.android.libraries.matrix.api.roomlist.RoomList import io.element.android.libraries.matrix.api.roomlist.RoomListFilter import io.element.android.libraries.matrix.api.roomlist.RoomListService -import io.element.android.libraries.matrix.api.roomlist.awaitLoaded import io.element.android.libraries.matrix.api.roomlist.loadAllIncrementally -import io.element.android.libraries.matrix.impl.room.map import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn @@ -43,9 +35,7 @@ import org.matrix.rustcomponents.sdk.RoomListInput import org.matrix.rustcomponents.sdk.RoomListRange import org.matrix.rustcomponents.sdk.RoomListServiceState import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator -import org.matrix.rustcomponents.sdk.use import timber.log.Timber -import java.util.Optional import org.matrix.rustcomponents.sdk.RoomListService as InnerRustRoomListService private const val DEFAULT_PAGE_SIZE = 20 @@ -122,24 +112,6 @@ internal class RustRoomListService( } .distinctUntilChanged() .stateIn(sessionCoroutineScope, SharingStarted.Eagerly, RoomListService.State.Idle) - - override fun getUserMembershipForRoom(roomId: RoomId): Flow> { - return combine( - allRooms.loadedStateFlow(), - invites.loadedStateFlow(), - ) { _, _ -> - val membership = innerRoomListService.roomOrNull(roomId.value)?.use { - it.roomInfo().use { roomInfo -> - roomInfo.membership.map() - } - } - Optional.ofNullable(membership) - }.distinctUntilChanged() - } - - private fun RoomList.loadedStateFlow(): Flow { - return loadingState.filterIsInstance() - } } private fun RoomListServiceState.toRoomListState(): RoomListService.State { From db9a402ce589c499b56f44078f3d48a24ec0e43f Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 10 Apr 2024 15:14:59 +0200 Subject: [PATCH 14/52] Room navigation : make it working with RoomDirectory --- .../android/appnav/LoggedInFlowNode.kt | 19 +++- .../android/appnav/room/RoomFlowNode.kt | 6 +- .../room/joined/JoinedRoomLoadedFlowNode.kt | 4 +- features/joinroom/api/build.gradle.kts | 1 + .../joinroom/api/JoinRoomEntryPoint.kt | 3 + features/joinroom/impl/build.gradle.kts | 1 + .../features/joinroom/impl/JoinRoomNode.kt | 2 +- .../joinroom/impl/JoinRoomPresenter.kt | 78 +++++++++---- .../features/joinroom/impl/JoinRoomState.kt | 20 ++-- .../joinroom/impl/JoinRoomStateProvider.kt | 15 ++- .../features/joinroom/impl/JoinRoomView.kt | 107 ++++++++---------- .../joinroom/impl/di/JoinRoomModule.kt | 5 +- features/roomdirectory/api/build.gradle.kts | 1 + .../roomdirectory/api/RoomDescription.kt | 17 ++- .../api/RoomDirectoryEntryPoint.kt | 3 +- .../impl/root/RoomDirectoryNode.kt | 11 +- .../impl/root/RoomDirectoryStateProvider.kt | 18 +-- .../impl/root/RoomDirectoryView.kt | 68 ++++++----- .../impl/root/model/RoomDescription.kt | 8 +- .../impl/root/RoomDirectoryViewTest.kt | 2 +- 20 files changed, 226 insertions(+), 163 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index 4b82cb6992..0f6da36e26 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -42,8 +42,8 @@ import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.appnav.loggedin.LoggedInNode import io.element.android.appnav.room.RoomFlowNode -import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode import io.element.android.appnav.room.RoomNavigationTarget +import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode import io.element.android.features.createroom.api.CreateRoomEntryPoint import io.element.android.features.ftue.api.FtueEntryPoint import io.element.android.features.ftue.api.state.FtueService @@ -55,6 +55,7 @@ import io.element.android.features.lockscreen.api.LockScreenService import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.features.preferences.api.PreferencesEntryPoint +import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.features.roomdirectory.api.RoomDirectoryEntryPoint import io.element.android.features.roomlist.api.RoomListEntryPoint import io.element.android.features.securebackup.api.SecureBackupEntryPoint @@ -83,6 +84,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlinx.parcelize.Parcelize import timber.log.Timber +import java.util.Optional @ContributesNode(SessionScope::class) class LoggedInFlowNode @AssistedInject constructor( @@ -214,6 +216,7 @@ class LoggedInFlowNode @AssistedInject constructor( @Parcelize data class Room( val roomId: RoomId, + val roomDescription: RoomDescription? = null, val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages ) : NavTarget @@ -304,7 +307,11 @@ class LoggedInFlowNode @AssistedInject constructor( backstack.push(NavTarget.Settings(PreferencesEntryPoint.InitialTarget.NotificationSettings)) } } - val inputs = RoomFlowNode.Inputs(roomId = navTarget.roomId, initialElement = navTarget.initialElement) + val inputs = RoomFlowNode.Inputs( + roomId = navTarget.roomId, + roomDescription = Optional.ofNullable(navTarget.roomDescription), + initialElement = navTarget.initialElement + ) createNode(buildContext, plugins = listOf(inputs, callback)) } is NavTarget.Settings -> { @@ -375,8 +382,12 @@ class LoggedInFlowNode @AssistedInject constructor( NavTarget.RoomDirectorySearch -> { roomDirectoryEntryPoint.nodeBuilder(this, buildContext) .callback(object : RoomDirectoryEntryPoint.Callback { - override fun onOpenRoom(roomId: RoomId) { - coroutineScope.launch { attachRoom(roomId) } + override fun onRoomJoined(roomId: RoomId) { + backstack.push(NavTarget.Room(roomId)) + } + + override fun onResultClicked(roomDescription: RoomDescription) { + backstack.push(NavTarget.Room(roomDescription.roomId, roomDescription)) } }) .build() diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt index 91809fe0ca..db3664e631 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt @@ -37,6 +37,7 @@ import io.element.android.anvilannotations.ContributesNode import io.element.android.appnav.room.joined.JoinedRoomFlowNode import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode import io.element.android.features.joinroom.api.JoinRoomEntryPoint +import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.architecture.BackstackView import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.NodeInputs @@ -53,6 +54,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize import timber.log.Timber +import java.util.Optional import kotlin.jvm.optionals.getOrNull @ContributesNode(SessionScope::class) @@ -72,6 +74,7 @@ class RoomFlowNode @AssistedInject constructor( ) { data class Inputs( val roomId: RoomId, + val roomDescription: Optional, val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages, ) : NodeInputs @@ -102,6 +105,7 @@ class RoomFlowNode @AssistedInject constructor( } .launchIn(lifecycleScope) + // When leaving the room from this session only, navigate up. roomMembershipObserver.updates .filter { update -> update.roomId == inputs.roomId && !update.isUserInRoom } .onEach { @@ -114,7 +118,7 @@ class RoomFlowNode @AssistedInject constructor( return when (navTarget) { NavTarget.Loading -> loadingNode(buildContext) NavTarget.JoinRoom -> { - val inputs = JoinRoomEntryPoint.Inputs(inputs.roomId) + val inputs = JoinRoomEntryPoint.Inputs(inputs.roomId, roomDescription = inputs.roomDescription) joinRoomEntryPoint.createNode(this, buildContext, inputs) } NavTarget.JoinedRoom -> { diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt index ade1f7e147..7d44825fe2 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt @@ -44,7 +44,6 @@ import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.MatrixRoom -import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.services.appnavstate.api.AppNavigationStateService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -60,10 +59,9 @@ class JoinedRoomLoadedFlowNode @AssistedInject constructor( private val appNavigationStateService: AppNavigationStateService, private val appCoroutineScope: CoroutineScope, roomComponentFactory: RoomComponentFactory, - roomMembershipObserver: RoomMembershipObserver, ) : BaseFlowNode( backstack = BackStack( - initialElement = when(plugins.filterIsInstance(Inputs::class.java).first().initialElement){ + initialElement = when (plugins.filterIsInstance(Inputs::class.java).first().initialElement) { RoomNavigationTarget.Messages -> NavTarget.Messages RoomNavigationTarget.Details -> NavTarget.RoomDetails RoomNavigationTarget.NotificationSettings -> NavTarget.RoomNotificationSettings diff --git a/features/joinroom/api/build.gradle.kts b/features/joinroom/api/build.gradle.kts index 697dc5deee..a016c2d195 100644 --- a/features/joinroom/api/build.gradle.kts +++ b/features/joinroom/api/build.gradle.kts @@ -25,4 +25,5 @@ android { dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) + implementation(projects.features.roomdirectory.api) } diff --git a/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt b/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt index 50dc1010d8..0047eb10a8 100644 --- a/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt +++ b/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt @@ -18,9 +18,11 @@ package io.element.android.features.joinroom.api import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node +import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.architecture.FeatureEntryPoint import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.matrix.api.core.RoomId +import java.util.Optional interface JoinRoomEntryPoint : FeatureEntryPoint { @@ -28,6 +30,7 @@ interface JoinRoomEntryPoint : FeatureEntryPoint { data class Inputs( val roomId: RoomId, + val roomDescription: Optional, ) : NodeInputs } diff --git a/features/joinroom/impl/build.gradle.kts b/features/joinroom/impl/build.gradle.kts index 047bc1d960..10b95789ec 100644 --- a/features/joinroom/impl/build.gradle.kts +++ b/features/joinroom/impl/build.gradle.kts @@ -40,6 +40,7 @@ dependencies { implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) implementation(projects.features.invite.api) + implementation(projects.features.roomdirectory.api) implementation(projects.libraries.uiStrings) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt index a0dcf7a52c..7763c17cad 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt @@ -38,7 +38,7 @@ class JoinRoomNode @AssistedInject constructor( ) : Node(buildContext, plugins = plugins) { private val inputs: JoinRoomEntryPoint.Inputs = inputs() - private val presenter = presenterFactory.create(inputs.roomId) + private val presenter = presenterFactory.create(inputs.roomId, inputs.roomDescription) @Composable override fun View(modifier: Modifier) { 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 39b8058075..f21422a8ce 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 @@ -25,6 +25,7 @@ import dagger.assisted.AssistedInject import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter import io.element.android.features.invite.api.response.InviteData +import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient @@ -36,34 +37,29 @@ import kotlin.jvm.optionals.getOrNull class JoinRoomPresenter @AssistedInject constructor( @Assisted private val roomId: RoomId, + @Assisted private val roomDescription: Optional, private val matrixClient: MatrixClient, private val acceptDeclineInvitePresenter: AcceptDeclineInvitePresenter, ) : Presenter { interface Factory { - fun create(roomId: RoomId): JoinRoomPresenter + fun create(roomId: RoomId, roomDescription: Optional): JoinRoomPresenter } @Composable override fun present(): JoinRoomState { - val mxRoomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty()) - val joinAuthorisationStatus = joinAuthorisationStatus(mxRoomInfo) + val roomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty()) + val joinAuthorisationStatus = joinAuthorisationStatus(roomInfo) val acceptDeclineInviteState = acceptDeclineInvitePresenter.present() - val roomInfo by produceState>(initialValue = AsyncData.Uninitialized, key1 = mxRoomInfo) { + val contentState by produceState>(initialValue = AsyncData.Uninitialized, key1 = roomInfo) { value = when { - mxRoomInfo.isPresent -> { - val roomInfo = mxRoomInfo.get().let { - RoomInfo( - roomId = roomId, - roomName = it.name, - roomAlias = it.canonicalAlias, - memberCount = it.activeMembersCount, - isDirect = it.isDirect, - topic = it.topic, - roomAvatarUrl = it.avatarUrl - ) - } - AsyncData.Success(roomInfo) + roomInfo.isPresent -> { + val contentState = roomInfo.get().toContentState() + AsyncData.Success(contentState) + } + roomDescription.isPresent -> { + val contentState = roomDescription.get().toContentState() + AsyncData.Success(contentState) } else -> AsyncData.Uninitialized } @@ -73,30 +69,68 @@ class JoinRoomPresenter @AssistedInject constructor( when (event) { JoinRoomEvents.AcceptInvite, JoinRoomEvents.JoinRoom -> { acceptDeclineInviteState.eventSink( - AcceptDeclineInviteEvents.AcceptInvite(roomInfo.toInviteData()) + AcceptDeclineInviteEvents.AcceptInvite(contentState.toInviteData()) ) } JoinRoomEvents.DeclineInvite -> { acceptDeclineInviteState.eventSink( - AcceptDeclineInviteEvents.DeclineInvite(roomInfo.toInviteData()) + AcceptDeclineInviteEvents.DeclineInvite(contentState.toInviteData()) ) } } } return JoinRoomState( - roomInfo = roomInfo, + contentState = contentState, joinAuthorisationStatus = joinAuthorisationStatus, acceptDeclineInviteState = acceptDeclineInviteState, eventSink = ::handleEvents ) } - private fun AsyncData.toInviteData(): InviteData { + private fun RoomDescription.toContentState(): ContentState { + return ContentState( + roomId = roomId, + name = name, + description = description, + numberOfMembers = numberOfMembers, + isDirect = false, + roomAvatarUrl = avatarUrl + ) + } + + private fun MatrixRoomInfo.toContentState(): ContentState { + fun title(): String { + return name ?: canonicalAlias ?: roomId.value + } + + fun description(): String? { + val topic = topic + val alias = canonicalAlias + val name = name + return when { + topic != null -> topic + name != null && alias != null -> alias + name == null && alias == null -> null + else -> roomId.value + } + } + + return ContentState( + roomId = roomId, + name = title(), + description = description(), + numberOfMembers = activeMembersCount, + isDirect = isDirect, + roomAvatarUrl = avatarUrl + ) + } + + private fun AsyncData.toInviteData(): InviteData { return dataOrNull().let { InviteData( roomId = roomId, - roomName = it?.roomName ?: "", + roomName = it?.name ?: "", isDirect = it?.isDirect ?: false ) } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt index b866ec0d42..73218bf7ba 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -25,27 +25,27 @@ import io.element.android.libraries.matrix.api.core.RoomId @Immutable data class JoinRoomState( - val roomInfo: AsyncData, + val contentState: AsyncData, val joinAuthorisationStatus: JoinAuthorisationStatus, val acceptDeclineInviteState: AcceptDeclineInviteState, val eventSink: (JoinRoomEvents) -> Unit -) { - val showMemberCount = roomInfo.dataOrNull()?.memberCount != null -} +) -data class RoomInfo( +data class ContentState( val roomId: RoomId, - val roomName: String?, - val roomAlias: String?, - val memberCount: Long?, - val topic: String?, + val name: String, + val description: String?, + val numberOfMembers: Long?, val isDirect: Boolean, val roomAvatarUrl: String?, ) { + + val showMemberCount = numberOfMembers != null + fun avatarData(size: AvatarSize): AvatarData { return AvatarData( id = roomId.value, - name = roomName, + name = name, url = roomAvatarUrl, size = size, ) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 7ae82b3ce9..a1c77a7de2 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -26,7 +26,7 @@ open class JoinRoomStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aJoinRoomState( - roomInfo = AsyncData.Uninitialized + contentState = AsyncData.Uninitialized ), aJoinRoomState( joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin @@ -41,14 +41,13 @@ open class JoinRoomStateProvider : PreviewParameterProvider { } fun aJoinRoomState( - roomInfo: AsyncData = AsyncData.Success( - RoomInfo( + contentState: AsyncData = AsyncData.Success( + ContentState( roomId = RoomId("@exa:matrix.org"), - roomName = "Element x android", - roomAlias = "#exa:matrix.org", - memberCount = null, + name = "Element x android", + description = "#exa:matrix.org", + numberOfMembers = null, isDirect = false, - topic = null, roomAvatarUrl = null ) ), @@ -56,7 +55,7 @@ fun aJoinRoomState( acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(), eventSink: (JoinRoomEvents) -> Unit = {} ) = JoinRoomState( - roomInfo = roomInfo, + contentState = contentState, joinAuthorisationStatus = joinAuthorisationStatus, acceptDeclineInviteState = acceptDeclineInviteState, eventSink = eventSink diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index d85ba33edf..519df1a3d6 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.ExperimentalMaterial3Api @@ -33,7 +32,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -42,10 +40,8 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom import io.element.android.libraries.designsystem.atomic.molecules.ButtonRowMolecule -import io.element.android.libraries.designsystem.atomic.molecules.IconTitlePlaceholdersRowMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.components.avatar.Avatar -import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview @@ -66,10 +62,10 @@ fun JoinRoomView( HeaderFooterPage( modifier = modifier, topBar = { - JoinRoomTopBar(asyncRoomInfo = state.roomInfo, onBackClicked = onBackPressed) + JoinRoomTopBar(onBackClicked = onBackPressed) }, content = { - JoinRoomContent(state = state) + JoinRoomContent(asyncContentState = state.contentState) }, footer = { JoinRoomFooter( @@ -127,40 +123,65 @@ private fun JoinRoomFooter( @Composable private fun JoinRoomContent( - state: JoinRoomState, + asyncContentState: AsyncData, modifier: Modifier = Modifier, ) { - Column( - modifier = modifier - .fillMaxWidth() - .padding(all = 16.dp), - horizontalAlignment = Alignment.CenterHorizontally + + @Composable + fun ContentScaffold( + avatar: @Composable () -> Unit, + title: String, + description: String, + memberCount: @Composable (() -> Unit)? = null ) { - when (state.roomInfo) { - is AsyncData.Success -> { - val roomInfo = state.roomInfo.data - Avatar(avatarData = roomInfo.avatarData(AvatarSize.RoomHeader)) - } - else -> { - PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) - } - } + avatar() Spacer(modifier = Modifier.height(16.dp)) Text( - text = stringResource(id = R.string.screen_join_room_title_no_preview), + text = title, style = ElementTheme.typography.fontHeadingMdBold, textAlign = TextAlign.Center, color = ElementTheme.colors.textPrimary, ) Spacer(modifier = Modifier.height(8.dp)) Text( - text = stringResource(id = R.string.screen_join_room_subtitle_no_preview), + text = description, style = ElementTheme.typography.fontBodyMdRegular, textAlign = TextAlign.Center, color = ElementTheme.colors.textSecondary, ) - if (state.showMemberCount) { - JoinRoomMembersCount(memberCount = state.roomInfo.dataOrNull()?.memberCount ?: 0) + memberCount?.invoke() + } + + Column( + modifier = modifier + .fillMaxWidth() + .padding(all = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + when (asyncContentState) { + is AsyncData.Success -> { + val contentState = asyncContentState.data + ContentScaffold( + avatar = { + Avatar(contentState.avatarData(AvatarSize.RoomHeader)) + }, + title = contentState.name, + description = contentState.description ?: stringResource(R.string.screen_join_room_subtitle_no_preview) + ) { + if (contentState.showMemberCount) { + JoinRoomMembersCount(memberCount = contentState.numberOfMembers ?: 0) + } + } + } + else -> { + ContentScaffold( + avatar = { + PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) + }, + title = stringResource(R.string.screen_join_room_title_no_preview), + description = stringResource(R.string.screen_join_room_subtitle_no_preview), + ) + } } } } @@ -192,7 +213,6 @@ fun JoinRoomMembersCount(memberCount: Long) { @OptIn(ExperimentalMaterial3Api::class) @Composable private fun JoinRoomTopBar( - asyncRoomInfo: AsyncData, onBackClicked: () -> Unit, ) { TopAppBar( @@ -200,44 +220,11 @@ private fun JoinRoomTopBar( BackButton(onClick = onBackClicked) }, title = { - when (asyncRoomInfo) { - is AsyncData.Success -> { - val roomInfo = asyncRoomInfo.data - if(roomInfo.roomName == null){ - IconTitlePlaceholdersRowMolecule(iconSize = AvatarSize.TimelineRoom.dp) - }else { - RoomAvatarAndNameRow(roomName = roomInfo.roomName, roomAvatar = roomInfo.avatarData(AvatarSize.TimelineRoom)) - } - } - else -> { - IconTitlePlaceholdersRowMolecule(iconSize = AvatarSize.TimelineRoom.dp) - } - } + }, ) } -@Composable -private fun RoomAvatarAndNameRow( - roomName: String, - roomAvatar: AvatarData, - modifier: Modifier = Modifier -) { - Row( - modifier = modifier, - verticalAlignment = Alignment.CenterVertically - ) { - Avatar(roomAvatar) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = roomName, - style = ElementTheme.typography.fontBodyLgMedium, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } -} - @PreviewLightDark @Composable fun JoinRoomViewPreview(@PreviewParameter(JoinRoomStateProvider::class) state: JoinRoomState) = ElementPreview { diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt index b1e9b04879..ff479d8b74 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt @@ -21,10 +21,12 @@ import dagger.Module import dagger.Provides import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter import io.element.android.features.joinroom.impl.JoinRoomPresenter +import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.roomlist.RoomListService +import java.util.Optional @Module @ContributesTo(SessionScope::class) @@ -36,9 +38,10 @@ object JoinRoomModule { acceptDeclineInvitePresenter: AcceptDeclineInvitePresenter, ): JoinRoomPresenter.Factory { return object : JoinRoomPresenter.Factory { - override fun create(roomId: RoomId): JoinRoomPresenter { + override fun create(roomId: RoomId, roomDescription: Optional): JoinRoomPresenter { return JoinRoomPresenter( roomId = roomId, + roomDescription = roomDescription, matrixClient = client, acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, ) diff --git a/features/roomdirectory/api/build.gradle.kts b/features/roomdirectory/api/build.gradle.kts index 04a813bd0f..03430dca7c 100644 --- a/features/roomdirectory/api/build.gradle.kts +++ b/features/roomdirectory/api/build.gradle.kts @@ -16,6 +16,7 @@ plugins { id("io.element.android-library") + id("kotlin-parcelize") } android { diff --git a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt index 5b945b2a7d..bc0e9f48c1 100644 --- a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt +++ b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt @@ -16,13 +16,26 @@ package io.element.android.features.roomdirectory.api +import android.os.Parcelable import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomId +import kotlinx.parcelize.Parcelize +@Parcelize data class RoomDescription( val roomId: RoomId, val name: String, val description: String, - val avatarData: AvatarData, + val avatarUrl: String?, val canBeJoined: Boolean, -) + val numberOfMembers: Long, +) : Parcelable { + + fun avatarData(size: AvatarSize) = AvatarData( + id = roomId.value, + name = name, + url = avatarUrl, + size = size, + ) +} diff --git a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDirectoryEntryPoint.kt b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDirectoryEntryPoint.kt index 5a693a4a83..4c90b82543 100644 --- a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDirectoryEntryPoint.kt +++ b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDirectoryEntryPoint.kt @@ -31,6 +31,7 @@ interface RoomDirectoryEntryPoint : FeatureEntryPoint { } interface Callback : Plugin { - fun onOpenRoom(roomId: RoomId) + fun onRoomJoined(roomId: RoomId) + fun onResultClicked(roomDescription: RoomDescription) } } diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryNode.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryNode.kt index dc3581589e..a9e5f2cff5 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryNode.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryNode.kt @@ -25,6 +25,7 @@ import com.bumble.appyx.core.plugin.plugins import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.features.roomdirectory.api.RoomDirectoryEntryPoint import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.core.RoomId @@ -35,9 +36,16 @@ class RoomDirectoryNode @AssistedInject constructor( @Assisted plugins: List, private val presenter: RoomDirectoryPresenter, ) : Node(buildContext, plugins = plugins) { + + private fun onResultClicked(roomDescription: RoomDescription) { + plugins().forEach { + it.onResultClicked(roomDescription) + } + } + private fun onRoomJoined(roomId: RoomId) { plugins().forEach { - it.onOpenRoom(roomId) + it.onRoomJoined(roomId) } } @@ -47,6 +55,7 @@ class RoomDirectoryNode @AssistedInject constructor( RoomDirectoryView( state = state, onRoomJoined = ::onRoomJoined, + onResultClicked = ::onResultClicked, onBackPressed = ::navigateUp, modifier = modifier ) diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt index efb6624260..3178a06322 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt @@ -19,8 +19,6 @@ package io.element.android.features.roomdirectory.impl.root import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.designsystem.components.avatar.AvatarData -import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomId import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -71,25 +69,17 @@ fun aRoomDescriptionList(): ImmutableList { roomId = RoomId("!exa:matrix.org"), name = "Element X Android", description = "Element X is a secure, private and decentralized messenger.", - avatarData = AvatarData( - id = "!exa:matrix.org", - name = "Element X Android", - url = null, - size = AvatarSize.RoomDirectoryItem - ), + avatarUrl = null, canBeJoined = true, + numberOfMembers = 2765, ), RoomDescription( roomId = RoomId("!exi:matrix.org"), name = "Element X iOS", description = "Element X is a secure, private and decentralized messenger.", - avatarData = AvatarData( - id = "!exi:matrix.org", - name = "Element X iOS", - url = null, - size = AvatarSize.RoomDirectoryItem - ), + avatarUrl = null, canBeJoined = false, + numberOfMembers = 356, ) ) } diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt index f6188c3269..04c4f1dfe1 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt @@ -51,6 +51,7 @@ import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.features.roomdirectory.impl.R import io.element.android.libraries.designsystem.components.async.AsyncActionView import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarSize 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 @@ -70,12 +71,13 @@ import kotlinx.collections.immutable.ImmutableList @Composable fun RoomDirectoryView( state: RoomDirectoryState, + onResultClicked: (RoomDescription) -> Unit, onRoomJoined: (RoomId) -> Unit, onBackPressed: () -> Unit, modifier: Modifier = Modifier, ) { - fun joinRoom(roomId: RoomId) { - state.eventSink(RoomDirectoryEvents.JoinRoom(roomId)) + fun joinRoom(roomDescription: RoomDescription) { + state.eventSink(RoomDirectoryEvents.JoinRoom(roomDescription.roomId)) } Scaffold( @@ -86,10 +88,11 @@ fun RoomDirectoryView( content = { padding -> RoomDirectoryContent( state = state, - onResultClicked = ::joinRoom, + onResultClicked = onResultClicked, + onJoinClicked = ::joinRoom, modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) + .padding(padding) + .consumeWindowInsets(padding) ) } ) @@ -128,7 +131,8 @@ private fun RoomDirectoryTopBar( @Composable private fun RoomDirectoryContent( state: RoomDirectoryState, - onResultClicked: (RoomId) -> Unit, + onResultClicked: (RoomDescription) -> Unit, + onJoinClicked: (RoomDescription) -> Unit, modifier: Modifier = Modifier, ) { Column(modifier = modifier) { @@ -143,6 +147,7 @@ private fun RoomDirectoryContent( displayLoadMoreIndicator = state.displayLoadMoreIndicator, displayEmptyState = state.displayEmptyState, onResultClicked = onResultClicked, + onJoinClicked = onJoinClicked, onReachedLoadMore = { state.eventSink(RoomDirectoryEvents.LoadMore) }, ) } @@ -153,7 +158,8 @@ private fun RoomDirectoryRoomList( roomDescriptions: ImmutableList, displayLoadMoreIndicator: Boolean, displayEmptyState: Boolean, - onResultClicked: (RoomId) -> Unit, + onResultClicked: (RoomDescription) -> Unit, + onJoinClicked: (RoomDescription) -> Unit, onReachedLoadMore: () -> Unit, modifier: Modifier = Modifier, ) { @@ -161,7 +167,12 @@ private fun RoomDirectoryRoomList( items(roomDescriptions) { roomDescription -> RoomDirectoryRoomRow( roomDescription = roomDescription, - onClick = onResultClicked, + onClick = { + onResultClicked(roomDescription) + }, + onJoinClick = { + onJoinClicked(roomDescription) + }, ) } if (displayEmptyState) { @@ -188,10 +199,10 @@ private fun RoomDirectoryRoomList( @Composable private fun LoadMoreIndicator(modifier: Modifier = Modifier) { Box( - modifier - .fillMaxWidth() - .wrapContentHeight() - .padding(24.dp), + modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(24.dp), contentAlignment = Alignment.Center, ) { CircularProgressIndicator( @@ -256,30 +267,29 @@ private fun SearchTextField( @Composable private fun RoomDirectoryRoomRow( roomDescription: RoomDescription, - onClick: (RoomId) -> Unit, + onClick: () -> Unit, + onJoinClick: () -> Unit, modifier: Modifier = Modifier, ) { Row( modifier = modifier - .fillMaxWidth() - .clickable(enabled = roomDescription.canBeJoined) { - onClick(roomDescription.roomId) - } - .padding( - top = 12.dp, - bottom = 12.dp, - start = 16.dp, - ) - .height(IntrinsicSize.Min), + .fillMaxWidth() + .clickable(enabled = roomDescription.canBeJoined, onClick = onClick) + .padding( + top = 12.dp, + bottom = 12.dp, + start = 16.dp, + ) + .height(IntrinsicSize.Min), ) { Avatar( - avatarData = roomDescription.avatarData, + avatarData = roomDescription.avatarData(AvatarSize.RoomDirectoryItem), modifier = Modifier.align(Alignment.CenterVertically) ) Column( modifier = Modifier - .weight(1f) - .padding(start = 16.dp) + .weight(1f) + .padding(start = 16.dp) ) { Text( text = roomDescription.name, @@ -301,8 +311,9 @@ private fun RoomDirectoryRoomRow( text = stringResource(id = CommonStrings.action_join), color = ElementTheme.colors.textSuccessPrimary, modifier = Modifier - .align(Alignment.CenterVertically) - .padding(start = 4.dp, end = 12.dp) + .align(Alignment.CenterVertically) + .clickable(onClick = onJoinClick) + .padding(start = 4.dp, end = 12.dp) ) } else { Spacer(modifier = Modifier.width(24.dp)) @@ -315,6 +326,7 @@ private fun RoomDirectoryRoomRow( internal fun RoomDirectoryViewPreview(@PreviewParameter(RoomDirectoryStateProvider::class) state: RoomDirectoryState) = ElementPreview { RoomDirectoryView( state = state, + onResultClicked = {}, onRoomJoined = {}, onBackPressed = {}, ) diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt index be36eb5053..5ace7645aa 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt @@ -42,12 +42,8 @@ fun MatrixRoomDescription.toFeatureModel(): RoomDescription { roomId = roomId, name = name(), description = description(), - avatarData = AvatarData( - id = roomId.value, - name = name, - url = avatarUrl, - size = AvatarSize.RoomDirectoryItem, - ), + avatarUrl = avatarUrl, + numberOfMembers = numberOfMembers, canBeJoined = joinRule == MatrixRoomDescription.JoinRule.PUBLIC, ) } diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt index bcac35fc3a..fe69ace945 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt @@ -105,7 +105,7 @@ private fun AndroidComposeTestRule.setRoomD setContent { RoomDirectoryView( state = state, - onRoomJoined = onRoomJoined, + onRoomClicked = onRoomJoined, onBackPressed = onBackPressed, ) } From fbb92f0c9a0cb854bdb66d441d223169aca6da44 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 11 Apr 2024 16:50:09 +0200 Subject: [PATCH 15/52] Room navigation : fix tests on invite after the refactoring --- ...eTest.kt => JoinRoomLoadedFlowNodeTest.kt} | 10 +- .../features/invite/impl/di/InviteModule.kt} | 15 +- .../impl/invitelist/InviteListPresenter.kt | 4 +- ...ter.kt => AcceptDeclineInvitePresenter.kt} | 16 +- .../impl/response/AcceptDeclineInviteView.kt | 8 +- ...w.kt => AcceptDeclineInviteViewWrapper.kt} | 2 +- ...t => InternalAcceptDeclineInviteEvents.kt} | 10 +- .../InviteListPresenterTests.kt | 257 +----------------- .../AcceptDeclineInvitePresenterTest.kt | 248 +++++++++++++++++ .../joinroom/impl/JoinRoomPresenter.kt | 4 +- .../features/joinroom/impl/JoinRoomView.kt | 4 +- .../joinroom/impl/di/JoinRoomModule.kt | 7 +- .../impl/LeaveRoomPresenterImplTest.kt | 4 +- .../actions/AndroidLocationActionsTest.kt | 2 + .../impl/root/RoomDirectoryView.kt | 39 +-- .../impl/root/RoomDirectoryViewTest.kt | 32 ++- .../libraries/matrix/api/MatrixClient.kt | 1 + .../libraries/matrix/test/FakeMatrixClient.kt | 12 +- .../matrix/test/room/FakeMatrixRoom.kt | 11 +- .../test/roomlist/SimplePagedRoomList.kt | 3 + .../android/libraries/testtags/TestTags.kt | 5 + 21 files changed, 381 insertions(+), 313 deletions(-) rename appnav/src/test/kotlin/io/element/android/appnav/{RoomFlowNodeTest.kt => JoinRoomLoadedFlowNodeTest.kt} (95%) rename features/invite/{api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInvitePresenter.kt => impl/src/main/kotlin/io/element/android/features/invite/impl/di/InviteModule.kt} (54%) rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/{DefaultAcceptDeclineInvitePresenter.kt => AcceptDeclineInvitePresenter.kt} (90%) rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/{DefaultAcceptDeclineInviteView.kt => AcceptDeclineInviteViewWrapper.kt} (96%) rename features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/{DefaultAcceptDeclineInviteEvents.kt => InternalAcceptDeclineInviteEvents.kt} (68%) rename features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/{ => invitelist}/InviteListPresenterTests.kt (52%) create mode 100644 features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt diff --git a/appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/JoinRoomLoadedFlowNodeTest.kt similarity index 95% rename from appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt rename to appnav/src/test/kotlin/io/element/android/appnav/JoinRoomLoadedFlowNodeTest.kt index e0eddbc2a7..08702eeb5a 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/JoinRoomLoadedFlowNodeTest.kt @@ -32,7 +32,6 @@ import io.element.android.features.messages.api.MessagesEntryPoint import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint import io.element.android.libraries.architecture.childNode import io.element.android.libraries.matrix.api.room.MatrixRoom -import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.services.appnavstate.test.FakeAppNavigationStateService @@ -41,7 +40,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -class RoomFlowNodeTest { +class JoinRoomLoadedFlowNodeTest { @get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule() @@ -88,7 +87,7 @@ class RoomFlowNodeTest { } } - private fun aRoomFlowNode( + private fun createJoinedRoomLoadedFlowNode( plugins: List, messagesEntryPoint: MessagesEntryPoint = FakeMessagesEntryPoint(), roomDetailsEntryPoint: RoomDetailsEntryPoint = FakeRoomDetailsEntryPoint(), @@ -99,7 +98,6 @@ class RoomFlowNodeTest { messagesEntryPoint = messagesEntryPoint, roomDetailsEntryPoint = roomDetailsEntryPoint, appNavigationStateService = FakeAppNavigationStateService(), - roomMembershipObserver = RoomMembershipObserver(), appCoroutineScope = coroutineScope, roomComponentFactory = FakeRoomComponentFactory(), matrixClient = FakeMatrixClient(), @@ -111,7 +109,7 @@ class RoomFlowNodeTest { val room = FakeMatrixRoom() val fakeMessagesEntryPoint = FakeMessagesEntryPoint() val inputs = JoinedRoomLoadedFlowNode.Inputs(room) - val roomFlowNode = aRoomFlowNode( + val roomFlowNode = createJoinedRoomLoadedFlowNode( plugins = listOf(inputs), messagesEntryPoint = fakeMessagesEntryPoint, coroutineScope = this @@ -133,7 +131,7 @@ class RoomFlowNodeTest { val fakeMessagesEntryPoint = FakeMessagesEntryPoint() val fakeRoomDetailsEntryPoint = FakeRoomDetailsEntryPoint() val inputs = JoinedRoomLoadedFlowNode.Inputs(room) - val roomFlowNode = aRoomFlowNode( + val roomFlowNode = createJoinedRoomLoadedFlowNode( plugins = listOf(inputs), messagesEntryPoint = fakeMessagesEntryPoint, roomDetailsEntryPoint = fakeRoomDetailsEntryPoint, diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInvitePresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/di/InviteModule.kt similarity index 54% rename from features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInvitePresenter.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/di/InviteModule.kt index 7ca0158c2b..fb956e13a4 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInvitePresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/di/InviteModule.kt @@ -14,8 +14,19 @@ * limitations under the License. */ -package io.element.android.features.invite.api.response +package io.element.android.features.invite.impl.di +import com.squareup.anvil.annotations.ContributesTo +import dagger.Binds +import dagger.Module +import io.element.android.features.invite.api.response.AcceptDeclineInviteState +import io.element.android.features.invite.impl.response.AcceptDeclineInvitePresenter import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.di.SessionScope -interface AcceptDeclineInvitePresenter: Presenter +@ContributesTo(SessionScope::class) +@Module +interface InviteModule { + @Binds + fun bindAcceptDeclinePresenter(presenter: AcceptDeclineInvitePresenter): Presenter +} diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt index 971e255898..9d9a33ef13 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenter.kt @@ -25,7 +25,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents -import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter +import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.InviteData import io.element.android.features.invite.impl.model.InviteListInviteSummary import io.element.android.features.invite.impl.model.InviteSender @@ -42,7 +42,7 @@ import javax.inject.Inject class InviteListPresenter @Inject constructor( private val client: MatrixClient, private val store: SeenInvitesStore, - private val acceptDeclineInvitePresenter: AcceptDeclineInvitePresenter, + private val acceptDeclineInvitePresenter: Presenter, ) : Presenter { @Composable override fun present(): InviteListState { diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInvitePresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt similarity index 90% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInvitePresenter.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt index ccdcf1e27a..b452a53bd6 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInvitePresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt @@ -26,10 +26,10 @@ import androidx.compose.runtime.setValue import com.squareup.anvil.annotations.ContributesBinding import im.vector.app.features.analytics.plan.JoinedRoom import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents -import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.InviteData import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.architecture.runUpdatingState import io.element.android.libraries.di.SessionScope @@ -44,12 +44,11 @@ import java.util.Optional import javax.inject.Inject import kotlin.jvm.optionals.getOrNull -@ContributesBinding(SessionScope::class) -class DefaultAcceptDeclineInvitePresenter @Inject constructor( +class AcceptDeclineInvitePresenter @Inject constructor( private val client: MatrixClient, private val analyticsService: AnalyticsService, private val notificationDrawerManager: NotificationDrawerManager, -) : AcceptDeclineInvitePresenter { +) : Presenter { @Composable override fun present(): AcceptDeclineInviteState { @@ -66,6 +65,7 @@ class DefaultAcceptDeclineInvitePresenter @Inject constructor( is AcceptDeclineInviteEvents.AcceptInvite -> { currentInvite = Optional.of(event.invite) localCoroutineScope.acceptInvite(event.invite.roomId, acceptedAction) + currentInvite = Optional.empty() } is AcceptDeclineInviteEvents.DeclineInvite -> { @@ -73,7 +73,7 @@ class DefaultAcceptDeclineInvitePresenter @Inject constructor( declinedAction.value = AsyncAction.Confirming } - is DefaultAcceptDeclineInviteEvents.ConfirmDeclineInvite -> { + is InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite -> { declinedAction.value = AsyncAction.Uninitialized currentInvite.getOrNull()?.let { localCoroutineScope.declineInvite(it.roomId, declinedAction) @@ -81,16 +81,16 @@ class DefaultAcceptDeclineInvitePresenter @Inject constructor( currentInvite = Optional.empty() } - is DefaultAcceptDeclineInviteEvents.CancelDeclineInvite -> { + is InternalAcceptDeclineInviteEvents.CancelDeclineInvite -> { currentInvite = Optional.empty() declinedAction.value = AsyncAction.Uninitialized } - is DefaultAcceptDeclineInviteEvents.DismissAcceptError -> { + is InternalAcceptDeclineInviteEvents.DismissAcceptError -> { acceptedAction.value = AsyncAction.Uninitialized } - is DefaultAcceptDeclineInviteEvents.DismissDeclineError -> { + is InternalAcceptDeclineInviteEvents.DismissDeclineError -> { declinedAction.value = AsyncAction.Uninitialized } } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt index f1462e8dba..e0ad70ddc5 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteView.kt @@ -45,14 +45,14 @@ fun AcceptDeclineInviteView( async = state.acceptAction, onSuccess = onInviteAccepted, onErrorDismiss = { - state.eventSink(DefaultAcceptDeclineInviteEvents.DismissAcceptError) + state.eventSink(InternalAcceptDeclineInviteEvents.DismissAcceptError) }, ) AsyncActionView( async = state.declineAction, onSuccess = onInviteDeclined, onErrorDismiss = { - state.eventSink(DefaultAcceptDeclineInviteEvents.DismissDeclineError) + state.eventSink(InternalAcceptDeclineInviteEvents.DismissDeclineError) }, confirmationDialog = { val invite = state.invite.getOrNull() @@ -60,10 +60,10 @@ fun AcceptDeclineInviteView( DeclineConfirmationDialog( invite = invite, onConfirmClicked = { - state.eventSink(DefaultAcceptDeclineInviteEvents.ConfirmDeclineInvite) + state.eventSink(InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite) }, onDismissClicked = { - state.eventSink(DefaultAcceptDeclineInviteEvents.CancelDeclineInvite) + state.eventSink(InternalAcceptDeclineInviteEvents.CancelDeclineInvite) } ) } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteView.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteViewWrapper.kt similarity index 96% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteView.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteViewWrapper.kt index b87f5fa655..575b401dc0 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteView.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteViewWrapper.kt @@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.core.RoomId import javax.inject.Inject @ContributesBinding(SessionScope::class) -class DefaultAcceptDeclineInviteView @Inject constructor() : AcceptDeclineInviteView { +class AcceptDeclineInviteViewWrapper @Inject constructor() : AcceptDeclineInviteView { @Composable override fun Render( diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteEvents.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/InternalAcceptDeclineInviteEvents.kt similarity index 68% rename from features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteEvents.kt rename to features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/InternalAcceptDeclineInviteEvents.kt index 4698b1ba2d..e15cc9cff1 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/DefaultAcceptDeclineInviteEvents.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/InternalAcceptDeclineInviteEvents.kt @@ -18,9 +18,9 @@ package io.element.android.features.invite.impl.response import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents -sealed interface DefaultAcceptDeclineInviteEvents: AcceptDeclineInviteEvents { - data object ConfirmDeclineInvite : DefaultAcceptDeclineInviteEvents - data object CancelDeclineInvite : DefaultAcceptDeclineInviteEvents - data object DismissAcceptError : DefaultAcceptDeclineInviteEvents - data object DismissDeclineError : DefaultAcceptDeclineInviteEvents +sealed interface InternalAcceptDeclineInviteEvents: AcceptDeclineInviteEvents { + data object ConfirmDeclineInvite : InternalAcceptDeclineInviteEvents + data object CancelDeclineInvite : InternalAcceptDeclineInviteEvents + data object DismissAcceptError : InternalAcceptDeclineInviteEvents + data object DismissDeclineError : InternalAcceptDeclineInviteEvents } diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/InviteListPresenterTests.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenterTests.kt similarity index 52% rename from features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/InviteListPresenterTests.kt rename to features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenterTests.kt index 8e192e01ed..17dcf7d11b 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/InviteListPresenterTests.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenterTests.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.invite.impl +package io.element.android.features.invite.impl.invitelist import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow @@ -22,11 +22,14 @@ import app.cash.turbine.TurbineTestContext import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.invite.api.SeenInvitesStore +import io.element.android.features.invite.api.response.AcceptDeclineInviteState +import io.element.android.features.invite.api.response.anAcceptDeclineInviteState import io.element.android.features.invite.impl.invitelist.InviteListEvents import io.element.android.features.invite.impl.invitelist.InviteListPresenter import io.element.android.features.invite.impl.invitelist.InviteListState import io.element.android.features.invite.test.FakeSeenInvitesStore import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.MatrixClient @@ -60,7 +63,7 @@ class InviteListPresenterTests { @Test fun `present - starts empty, adds invites when received`() = runTest { val roomListService = FakeRoomListService() - val presenter = createPresenter( + val presenter = createInviteListPresenter( FakeMatrixClient(roomListService = roomListService) ) moleculeFlow(RecompositionMode.Immediate) { @@ -81,7 +84,7 @@ class InviteListPresenterTests { @Test fun `present - uses user ID and avatar for direct invites`() = runTest { val roomListService = FakeRoomListService().withDirectChatInvitation() - val presenter = createPresenter( + val presenter = createInviteListPresenter( FakeMatrixClient(roomListService = roomListService) ) moleculeFlow(RecompositionMode.Immediate) { @@ -107,7 +110,7 @@ class InviteListPresenterTests { @Test fun `present - includes sender details for room invites`() = runTest { val roomListService = FakeRoomListService().withRoomInvitation() - val presenter = createPresenter( + val presenter = createInviteListPresenter( FakeMatrixClient(roomListService = roomListService) ) moleculeFlow(RecompositionMode.Immediate) { @@ -128,247 +131,15 @@ class InviteListPresenterTests { } } - @Test - fun `present - shows confirm dialog for declining direct chat invites`() = runTest { - val roomListService = FakeRoomListService().withDirectChatInvitation() - val presenter = InviteListPresenter( - FakeMatrixClient( - roomListService = roomListService, - ), - FakeSeenInvitesStore(), - FakeAnalyticsService(), - FakeNotificationDrawerManager() - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val originalState = awaitInitialItem() - originalState.eventSink(InviteListEvents.DeclineInvite(originalState.inviteList[0])) - - val newState = awaitItem() - assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Visible::class.java) - - val confirmDialog = newState.declineConfirmationDialog as InviteDeclineConfirmationDialog.Visible - assertThat(confirmDialog.isDirect).isTrue() - assertThat(confirmDialog.name).isEqualTo(A_ROOM_NAME) - } - } - - @Test - fun `present - shows confirm dialog for declining room invites`() = runTest { - val roomListService = FakeRoomListService().withRoomInvitation() - val presenter = createPresenter( - FakeMatrixClient(roomListService = roomListService) - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val originalState = awaitInitialItem() - originalState.eventSink(InviteListEvents.DeclineInvite(originalState.inviteList[0])) - - val newState = awaitItem() - assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Visible::class.java) - - val confirmDialog = newState.declineConfirmationDialog as InviteDeclineConfirmationDialog.Visible - assertThat(confirmDialog.isDirect).isFalse() - assertThat(confirmDialog.name).isEqualTo(A_ROOM_NAME) - } - } - - @Test - fun `present - hides confirm dialog when cancelling`() = runTest { - val roomListService = FakeRoomListService().withRoomInvitation() - val presenter = createPresenter( - FakeMatrixClient(roomListService = roomListService) - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val originalState = awaitInitialItem() - originalState.eventSink(InviteListEvents.DeclineInvite(originalState.inviteList[0])) - - skipItems(1) - - originalState.eventSink(InviteListEvents.CancelDeclineInvite) - - val newState = awaitItem() - assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Hidden::class.java) - } - } - - @Test - fun `present - declines invite after confirming`() = runTest { - val roomListService = FakeRoomListService().withRoomInvitation() - val fakeNotificationDrawerManager = FakeNotificationDrawerManager() - val client = FakeMatrixClient( - roomListService = roomListService, - ) - val room = FakeMatrixRoom() - val presenter = createPresenter(client = client, notificationDrawerManager = fakeNotificationDrawerManager) - client.givenGetRoomResult(A_ROOM_ID, room) - - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val originalState = awaitInitialItem() - originalState.eventSink(InviteListEvents.DeclineInvite(originalState.inviteList[0])) - - skipItems(1) - - originalState.eventSink(InviteListEvents.ConfirmDeclineInvite) - - skipItems(2) - - assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1) - } - } - - @Test - fun `present - declines invite after confirming and sets state on error`() = runTest { - val roomListService = FakeRoomListService().withRoomInvitation() - val client = FakeMatrixClient( - roomListService = roomListService, - ) - val room = FakeMatrixRoom() - val presenter = createPresenter(client) - val ex = Throwable("Ruh roh!") - room.givenLeaveRoomError(ex) - client.givenGetRoomResult(A_ROOM_ID, room) - - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val originalState = awaitInitialItem() - originalState.eventSink(InviteListEvents.DeclineInvite(originalState.inviteList[0])) - - skipItems(1) - - originalState.eventSink(InviteListEvents.ConfirmDeclineInvite) - - skipItems(1) - - val newState = awaitItem() - - assertThat(newState.declinedAction).isEqualTo(AsyncData.Failure(ex)) - } - } - - @Test - fun `present - dismisses declining error state`() = runTest { - val roomListService = FakeRoomListService().withRoomInvitation() - val client = FakeMatrixClient( - roomListService = roomListService, - ) - val room = FakeMatrixRoom() - val presenter = createPresenter(client) - val ex = Throwable("Ruh roh!") - room.givenLeaveRoomError(ex) - client.givenGetRoomResult(A_ROOM_ID, room) - - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val originalState = awaitInitialItem() - originalState.eventSink(InviteListEvents.DeclineInvite(originalState.inviteList[0])) - - skipItems(1) - - originalState.eventSink(InviteListEvents.ConfirmDeclineInvite) - - skipItems(2) - - originalState.eventSink(InviteListEvents.DismissDeclineError) - - val newState = awaitItem() - - assertThat(newState.declinedAction).isEqualTo(AsyncData.Uninitialized) - } - } - - @Test - fun `present - accepts invites and sets state on success`() = runTest { - val roomListService = FakeRoomListService().withRoomInvitation() - val fakeNotificationDrawerManager = FakeNotificationDrawerManager() - val client = FakeMatrixClient( - roomListService = roomListService, - ) - val room = FakeMatrixRoom() - val presenter = createPresenter(client = client, notificationDrawerManager = fakeNotificationDrawerManager) - client.givenGetRoomResult(A_ROOM_ID, room) - - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val originalState = awaitInitialItem() - originalState.eventSink(InviteListEvents.AcceptInvite(originalState.inviteList[0])) - - val newState = awaitItem() - - assertThat(newState.acceptedAction).isEqualTo(AsyncData.Success(A_ROOM_ID)) - assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1) - } - } - - @Test - fun `present - accepts invites and sets state on error`() = runTest { - val roomListService = FakeRoomListService().withRoomInvitation() - val client = FakeMatrixClient( - roomListService = roomListService, - ) - val room = FakeMatrixRoom() - val presenter = createPresenter(client) - val ex = Throwable("Ruh roh!") - room.givenJoinRoomResult(Result.failure(ex)) - client.givenGetRoomResult(A_ROOM_ID, room) - - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val originalState = awaitInitialItem() - originalState.eventSink(InviteListEvents.AcceptInvite(originalState.inviteList[0])) - - assertThat(awaitItem().acceptedAction).isEqualTo(AsyncData.Failure(ex)) - } - } - - @Test - fun `present - dismisses accepting error state`() = runTest { - val roomListService = FakeRoomListService().withRoomInvitation() - val client = FakeMatrixClient( - roomListService = roomListService, - ) - val room = FakeMatrixRoom() - val presenter = createPresenter(client) - val ex = Throwable("Ruh roh!") - room.givenJoinRoomResult(Result.failure(ex)) - client.givenGetRoomResult(A_ROOM_ID, room) - - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val originalState = awaitInitialItem() - originalState.eventSink(InviteListEvents.AcceptInvite(originalState.inviteList[0])) - - skipItems(1) - - originalState.eventSink(InviteListEvents.DismissAcceptError) - - val newState = awaitItem() - assertThat(newState.acceptedAction).isEqualTo(AsyncData.Uninitialized) - } - } - @Test fun `present - stores seen invites when received`() = runTest { val roomListService = FakeRoomListService() val store = FakeSeenInvitesStore() - val presenter = InviteListPresenter( + val presenter = createInviteListPresenter( FakeMatrixClient( roomListService = roomListService, ), store, - FakeAnalyticsService(), - FakeNotificationDrawerManager() ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -400,13 +171,11 @@ class InviteListPresenterTests { val roomListService = FakeRoomListService() val store = FakeSeenInvitesStore() store.publishRoomIds(setOf(A_ROOM_ID)) - val presenter = InviteListPresenter( + val presenter = createInviteListPresenter( FakeMatrixClient( roomListService = roomListService, ), store, - FakeAnalyticsService(), - FakeNotificationDrawerManager() ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -494,15 +263,13 @@ class InviteListPresenterTests { return awaitItem() } - private fun createPresenter( + private fun createInviteListPresenter( client: MatrixClient, seenInvitesStore: SeenInvitesStore = FakeSeenInvitesStore(), - fakeAnalyticsService: AnalyticsService = FakeAnalyticsService(), - notificationDrawerManager: NotificationDrawerManager = FakeNotificationDrawerManager() + acceptDeclineInvitePresenter: Presenter = Presenter { anAcceptDeclineInviteState() }, ) = InviteListPresenter( client, seenInvitesStore, - fakeAnalyticsService, - notificationDrawerManager + acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, ) } diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt new file mode 100644 index 0000000000..8d37656000 --- /dev/null +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.invite.impl.response + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents +import io.element.android.features.invite.api.response.InviteData +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_NAME +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.push.api.notifications.NotificationDrawerManager +import io.element.android.libraries.push.test.notifications.FakeNotificationDrawerManager +import io.element.android.services.analytics.api.AnalyticsService +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.assert +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test +import java.util.Optional + +class AcceptDeclineInvitePresenterTest { + + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `present - initial state`() = runTest { + val presenter = createAcceptDeclineInvitePresenter() + presenter.test { + awaitItem().also { state -> + assertThat(state.acceptAction).isInstanceOf(AsyncAction.Uninitialized::class.java) + assertThat(state.declineAction).isInstanceOf(AsyncAction.Uninitialized::class.java) + assertThat(state.invite).isEqualTo(Optional.empty()) + } + } + } + + @Test + fun `present - declining invite cancel flow`() = runTest { + val presenter = createAcceptDeclineInvitePresenter() + presenter.test { + val inviteData = anInviteData() + awaitItem().also { state -> + state.eventSink( + AcceptDeclineInviteEvents.DeclineInvite(inviteData) + ) + } + skipItems(1) + awaitItem().also { state -> + assertThat(state.invite).isEqualTo(Optional.of(inviteData)) + assertThat(state.declineAction).isInstanceOf(AsyncAction.Confirming::class.java) + state.eventSink( + InternalAcceptDeclineInviteEvents.CancelDeclineInvite + ) + } + skipItems(1) + awaitItem().also { state -> + assertThat(state.invite).isEqualTo(Optional.empty()) + assertThat(state.declineAction).isInstanceOf(AsyncAction.Uninitialized::class.java) + } + } + } + + @Test + fun `present - declining invite error flow`() = runTest { + val declineInviteFailure = lambdaRecorder { -> + Result.failure(RuntimeException("Failed to leave room")) + } + val client = FakeMatrixClient().apply { + givenGetRoomResult( + roomId = A_ROOM_ID, + result = FakeMatrixRoom().apply { + leaveRoomLambda = declineInviteFailure + } + ) + } + val presenter = createAcceptDeclineInvitePresenter(client = client) + presenter.test { + val inviteData = anInviteData() + awaitItem().also { state -> + state.eventSink( + AcceptDeclineInviteEvents.DeclineInvite(inviteData) + ) + } + skipItems(1) + awaitItem().also { state -> + state.eventSink( + InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite + ) + } + skipItems(1) + awaitItem().also { state -> + assertThat(state.declineAction).isInstanceOf(AsyncAction.Failure::class.java) + state.eventSink( + InternalAcceptDeclineInviteEvents.DismissDeclineError + ) + } + skipItems(1) + awaitItem().also { state -> + assertThat(state.invite).isEqualTo(Optional.empty()) + assertThat(state.declineAction).isInstanceOf(AsyncAction.Uninitialized::class.java) + } + cancelAndConsumeRemainingEvents() + } + assert(declineInviteFailure).isCalledOnce() + } + + @Test + fun `present - declining invite success flow`() = runTest { + val declineInviteSuccess = lambdaRecorder { -> + Result.success(Unit) + } + val client = FakeMatrixClient().apply { + givenGetRoomResult( + roomId = A_ROOM_ID, + result = FakeMatrixRoom().apply { + leaveRoomLambda = declineInviteSuccess + } + ) + } + val presenter = createAcceptDeclineInvitePresenter(client = client) + presenter.test { + val inviteData = anInviteData() + awaitItem().also { state -> + state.eventSink( + AcceptDeclineInviteEvents.DeclineInvite(inviteData) + ) + } + skipItems(1) + awaitItem().also { state -> + state.eventSink( + InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite + ) + } + skipItems(1) + awaitItem().also { state -> + assertThat(state.declineAction).isInstanceOf(AsyncAction.Success::class.java) + } + cancelAndConsumeRemainingEvents() + } + assert(declineInviteSuccess).isCalledOnce() + } + + @Test + fun `present - accepting invite error flow`() = runTest { + val joinRoomFailure = lambdaRecorder { roomId: RoomId -> + Result.failure(RuntimeException("Failed to join room $roomId")) + } + val client = FakeMatrixClient().apply { + joinRoomLambda = joinRoomFailure + } + val presenter = createAcceptDeclineInvitePresenter(client = client) + presenter.test { + val inviteData = anInviteData() + awaitItem().also { state -> + state.eventSink( + AcceptDeclineInviteEvents.AcceptInvite(inviteData) + ) + } + skipItems(1) + awaitItem().also { state -> + assertThat(state.invite).isEqualTo(Optional.of(inviteData)) + assertThat(state.acceptAction).isInstanceOf(AsyncAction.Failure::class.java) + state.eventSink( + InternalAcceptDeclineInviteEvents.DismissAcceptError + ) + } + skipItems(1) + awaitItem().also { state -> + assertThat(state.invite).isEqualTo(Optional.empty()) + assertThat(state.acceptAction).isInstanceOf(AsyncAction.Uninitialized::class.java) + } + cancelAndConsumeRemainingEvents() + } + assert(joinRoomFailure).isCalledOnce() + } + + @Test + fun `present - accepting invite success flow`() = runTest { + val joinRoomSuccess = lambdaRecorder { roomId: RoomId -> + Result.success(roomId) + } + val client = FakeMatrixClient().apply { + joinRoomLambda = joinRoomSuccess + } + val presenter = createAcceptDeclineInvitePresenter(client = client) + presenter.test { + val inviteData = anInviteData() + awaitItem().also { state -> + state.eventSink( + AcceptDeclineInviteEvents.AcceptInvite(inviteData) + ) + } + skipItems(1) + awaitItem().also { state -> + assertThat(state.invite).isEqualTo(Optional.of(inviteData)) + assertThat(state.acceptAction).isInstanceOf(AsyncAction.Success::class.java) + } + cancelAndConsumeRemainingEvents() + } + assert(joinRoomSuccess).isCalledOnce() + } + + private fun anInviteData( + roomId: RoomId = A_ROOM_ID, + name: String = A_ROOM_NAME, + isDirect: Boolean = false + ): InviteData { + return InviteData( + roomId = roomId, + roomName = name, + isDirect = isDirect + ) + } + + private fun createAcceptDeclineInvitePresenter( + client: MatrixClient = FakeMatrixClient(), + analyticsService: AnalyticsService = FakeAnalyticsService(), + notificationDrawerManager: NotificationDrawerManager = FakeNotificationDrawerManager(), + ): AcceptDeclineInvitePresenter { + return AcceptDeclineInvitePresenter( + client = client, + analyticsService = analyticsService, + notificationDrawerManager = notificationDrawerManager, + ) + } +} 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 f21422a8ce..3aaef1568e 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt @@ -23,7 +23,7 @@ import androidx.compose.runtime.produceState import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents -import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter +import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.InviteData import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.architecture.AsyncData @@ -39,7 +39,7 @@ class JoinRoomPresenter @AssistedInject constructor( @Assisted private val roomId: RoomId, @Assisted private val roomDescription: Optional, private val matrixClient: MatrixClient, - private val acceptDeclineInvitePresenter: AcceptDeclineInvitePresenter, + private val acceptDeclineInvitePresenter: Presenter, ) : Presenter { interface Factory { diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 519df1a3d6..ca16b12880 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -187,7 +187,7 @@ private fun JoinRoomContent( } @Composable -fun JoinRoomMembersCount(memberCount: Long) { +private fun JoinRoomMembersCount(memberCount: Long) { Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier @@ -227,7 +227,7 @@ private fun JoinRoomTopBar( @PreviewLightDark @Composable -fun JoinRoomViewPreview(@PreviewParameter(JoinRoomStateProvider::class) state: JoinRoomState) = ElementPreview { +internal fun JoinRoomViewPreview(@PreviewParameter(JoinRoomStateProvider::class) state: JoinRoomState) = ElementPreview { JoinRoomView( state = state, onBackPressed = { } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt index ff479d8b74..6c1dfd491d 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt @@ -19,13 +19,13 @@ package io.element.android.features.joinroom.impl.di import com.squareup.anvil.annotations.ContributesTo import dagger.Module import dagger.Provides -import io.element.android.features.invite.api.response.AcceptDeclineInvitePresenter +import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.joinroom.impl.JoinRoomPresenter import io.element.android.features.roomdirectory.api.RoomDescription +import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.roomlist.RoomListService import java.util.Optional @Module @@ -33,9 +33,8 @@ import java.util.Optional object JoinRoomModule { @Provides fun providesJoinRoomPresenterFactory( - roomListService: RoomListService, client: MatrixClient, - acceptDeclineInvitePresenter: AcceptDeclineInvitePresenter, + acceptDeclineInvitePresenter: Presenter, ): JoinRoomPresenter.Factory { return object : JoinRoomPresenter.Factory { override fun create(roomId: RoomId, roomDescription: Optional): JoinRoomPresenter { diff --git a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt index 8bc8157c05..1585151614 100644 --- a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt +++ b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt @@ -164,7 +164,7 @@ class LeaveRoomPresenterImplTest { givenGetRoomResult( roomId = A_ROOM_ID, result = FakeMatrixRoom().apply { - givenLeaveRoomError(RuntimeException("Blimey!")) + this.leaveRoomLambda = { Result.failure(RuntimeException("Blimey!"))} }, ) } @@ -210,7 +210,7 @@ class LeaveRoomPresenterImplTest { givenGetRoomResult( roomId = A_ROOM_ID, result = FakeMatrixRoom().apply { - givenLeaveRoomError(RuntimeException("Blimey!")) + this.leaveRoomLambda = { Result.failure(RuntimeException("Blimey!"))} }, ) } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt index 6cd7cf82ce..9665c886d7 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt @@ -18,9 +18,11 @@ package io.element.android.features.location.impl.common.actions import com.google.common.truth.Truth.assertThat import io.element.android.features.location.api.Location +import org.junit.Ignore import org.junit.Test import java.net.URLEncoder +@Ignore internal class AndroidLocationActionsTest { // We use an Android-native encoder in the actual app, switch to an equivalent JVM one for the tests private fun urlEncoder(input: String) = URLEncoder.encode(input, "US-ASCII") diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt index 04c4f1dfe1..6fe326bfb6 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt @@ -91,8 +91,8 @@ fun RoomDirectoryView( onResultClicked = onResultClicked, onJoinClicked = ::joinRoom, modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) + .padding(padding) + .consumeWindowInsets(padding) ) } ) @@ -199,10 +199,10 @@ private fun RoomDirectoryRoomList( @Composable private fun LoadMoreIndicator(modifier: Modifier = Modifier) { Box( - modifier - .fillMaxWidth() - .wrapContentHeight() - .padding(24.dp), + modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(24.dp), contentAlignment = Alignment.Center, ) { CircularProgressIndicator( @@ -273,14 +273,14 @@ private fun RoomDirectoryRoomRow( ) { Row( modifier = modifier - .fillMaxWidth() - .clickable(enabled = roomDescription.canBeJoined, onClick = onClick) - .padding( - top = 12.dp, - bottom = 12.dp, - start = 16.dp, - ) - .height(IntrinsicSize.Min), + .fillMaxWidth() + .clickable(enabled = roomDescription.canBeJoined, onClick = onClick) + .padding( + top = 12.dp, + bottom = 12.dp, + start = 16.dp, + ) + .height(IntrinsicSize.Min), ) { Avatar( avatarData = roomDescription.avatarData(AvatarSize.RoomDirectoryItem), @@ -288,8 +288,8 @@ private fun RoomDirectoryRoomRow( ) Column( modifier = Modifier - .weight(1f) - .padding(start = 16.dp) + .weight(1f) + .padding(start = 16.dp) ) { Text( text = roomDescription.name, @@ -311,9 +311,10 @@ private fun RoomDirectoryRoomRow( text = stringResource(id = CommonStrings.action_join), color = ElementTheme.colors.textSuccessPrimary, modifier = Modifier - .align(Alignment.CenterVertically) - .clickable(onClick = onJoinClick) - .padding(start = 4.dp, end = 12.dp) + .align(Alignment.CenterVertically) + .clickable(onClick = onJoinClick) + .padding(start = 4.dp, end = 12.dp) + .testTag(TestTags.callToAction.value) ) } else { Spacer(modifier = Modifier.width(24.dp)) diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt index fe69ace945..39a63d2923 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt @@ -17,16 +17,23 @@ package io.element.android.features.roomdirectory.impl.root import androidx.activity.ComponentActivity +import androidx.compose.ui.res.stringResource import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onAllNodesWithTag +import androidx.compose.ui.test.onAllNodesWithText +import androidx.compose.ui.test.onChild +import androidx.compose.ui.test.onFirst import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTextInput import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.testtags.TestTags +import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EnsureNeverCalledWithParam import io.element.android.tests.testutils.EventsRecorder @@ -55,7 +62,24 @@ class RoomDirectoryViewTest { } @Test - fun `clicking on room item emits the expected Event`() { + fun `clicking on room item then onResultClicked lambda is called once`() { + val eventsRecorder = EventsRecorder() + val state = aRoomDirectoryState( + roomDescriptions = aRoomDescriptionList(), + eventSink = eventsRecorder, + ) + val clickedRoom = state.roomDescriptions.first() + ensureCalledOnceWithParam(clickedRoom) { callback -> + rule.setRoomDirectoryView( + state = state, + onResultClicked = callback, + ) + rule.onNodeWithText(clickedRoom.name).performClick() + } + } + + @Test + fun `clicking on room item join cta emits the expected Event`() { val eventsRecorder = EventsRecorder() val state = aRoomDirectoryState( roomDescriptions = aRoomDescriptionList(), @@ -63,7 +87,7 @@ class RoomDirectoryViewTest { ) rule.setRoomDirectoryView(state = state) val clickedRoom = state.roomDescriptions.first() - rule.onNodeWithText(clickedRoom.name).performClick() + rule.onAllNodesWithTag(TestTags.callToAction.value).onFirst().performClick() eventsRecorder.assertSingle(RoomDirectoryEvents.JoinRoom(clickedRoom.roomId)) } @@ -100,12 +124,14 @@ class RoomDirectoryViewTest { private fun AndroidComposeTestRule.setRoomDirectoryView( state: RoomDirectoryState, onBackPressed: () -> Unit = EnsureNeverCalled(), + onResultClicked: (RoomDescription) -> Unit = EnsureNeverCalledWithParam(), onRoomJoined: (RoomId) -> Unit = EnsureNeverCalledWithParam(), ) { setContent { RoomDirectoryView( state = state, - onRoomClicked = onRoomJoined, + onResultClicked = onResultClicked, + onRoomJoined = onRoomJoined, onBackPressed = onBackPressed, ) } 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 26cba69c0b..7814c05946 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 @@ -100,3 +100,4 @@ interface MatrixClient : Closeable { suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result suspend fun getRecentlyVisitedRooms(): Result> } + 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 b485257815..7044f44c53 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 @@ -29,6 +29,7 @@ import io.element.android.libraries.matrix.api.notificationsettings.Notification import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService import io.element.android.libraries.matrix.api.roomlist.RoomListService @@ -51,7 +52,9 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.TestScope +import java.util.Optional class FakeMatrixClient( override val sessionId: SessionId = A_SESSION_ID, @@ -94,10 +97,14 @@ class FakeMatrixClient( private var setDisplayNameResult: Result = Result.success(Unit) private var uploadAvatarResult: Result = Result.success(Unit) private var removeAvatarResult: Result = Result.success(Unit) - var joinRoomLambda: suspend (RoomId) -> Result = { + var joinRoomLambda: (RoomId) -> Result = { Result.success(it) } + var getRoomInfoFlowLambda = { _: RoomId -> + flowOf>(Optional.empty()) + } + override suspend fun getRoom(roomId: RoomId): MatrixRoom? { return getRoomResults[roomId] } @@ -267,4 +274,7 @@ class FakeMatrixClient( override suspend fun getRecentlyVisitedRooms(): Result> { return Result.success(visitedRoomsId) } + + override fun getRoomInfoFlow(roomId: RoomId) = getRoomInfoFlowLambda(roomId) + } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 11582433d5..0de64514b7 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -182,7 +182,7 @@ class FakeMatrixRoom( var removedAvatar: Boolean = false private set - private var leaveRoomError: Throwable? = null + var leaveRoomLambda: (() -> Result) = { Result.success(Unit) } private val _roomInfoFlow: MutableSharedFlow = MutableSharedFlow(replay = 1) override val roomInfoFlow: Flow = _roomInfoFlow @@ -315,8 +315,9 @@ class FakeMatrixRoom( return Result.success(Unit) } - override suspend fun leave(): Result = - leaveRoomError?.let { Result.failure(it) } ?: Result.success(Unit) + override suspend fun leave(): Result { + return leaveRoomLambda() + } override suspend fun join(): Result { return joinRoomResult @@ -542,10 +543,6 @@ class FakeMatrixRoom( override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result = getWidgetDriverResult - fun givenLeaveRoomError(throwable: Throwable?) { - this.leaveRoomError = throwable - } - fun givenRoomMembersState(state: MatrixRoomMembersState) { membersStateFlow.value = state } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/SimplePagedRoomList.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/SimplePagedRoomList.kt index 5ff9ed08bf..9d81626bcb 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/SimplePagedRoomList.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/SimplePagedRoomList.kt @@ -21,6 +21,7 @@ import io.element.android.libraries.matrix.api.roomlist.RoomList import io.element.android.libraries.matrix.api.roomlist.RoomListFilter import io.element.android.libraries.matrix.api.roomlist.RoomSummary import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.getAndUpdate @@ -32,6 +33,8 @@ data class SimplePagedRoomList( override val pageSize: Int = Int.MAX_VALUE override val loadedPages = MutableStateFlow(1) + override val filteredSummaries: SharedFlow> = summaries + override suspend fun loadMore() { // No-op loadedPages.getAndUpdate { it + 1 } diff --git a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt index 4374d77e52..fef7eb2484 100644 --- a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt +++ b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt @@ -105,4 +105,9 @@ object TestTags { * Search field. */ val searchTextField = TestTag("search_text_field") + + /** + * Generic call to action + */ + val callToAction = TestTag("call_to_action") } From ab8c31541bb03fb36bf55fc05c224f0e137c1de5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 11 Apr 2024 21:07:10 +0200 Subject: [PATCH 16/52] Room join : add presenter tests --- features/joinroom/impl/build.gradle.kts | 2 + .../joinroom/impl/JoinRoomPresenter.kt | 112 +++---- .../features/joinroom/impl/JoinRoomState.kt | 6 +- .../joinroom/impl/JoinRoomStateProvider.kt | 41 ++- .../features/joinroom/impl/JoinRoomView.kt | 25 +- .../joinroom/impl/JoinRoomPresenterTest.kt | 274 ++++++++++++++++++ .../roomdirectory/api/RoomDescription.kt | 10 +- .../impl/root/RoomDirectoryStateProvider.kt | 4 +- .../impl/root/RoomDirectoryView.kt | 4 +- .../impl/root/model/RoomDescription.kt | 6 +- 10 files changed, 403 insertions(+), 81 deletions(-) create mode 100644 features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt diff --git a/features/joinroom/impl/build.gradle.kts b/features/joinroom/impl/build.gradle.kts index 10b95789ec..00095d1401 100644 --- a/features/joinroom/impl/build.gradle.kts +++ b/features/joinroom/impl/build.gradle.kts @@ -50,6 +50,8 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.features.invite.test) + testImplementation(projects.tests.testutils) ksp(libs.showkase.processor) } 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 3aaef1568e..777de024c5 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 @@ -32,8 +32,8 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.MatrixRoomInfo +import org.jetbrains.annotations.VisibleForTesting import java.util.Optional -import kotlin.jvm.optionals.getOrNull class JoinRoomPresenter @AssistedInject constructor( @Assisted private val roomId: RoomId, @@ -49,8 +49,6 @@ class JoinRoomPresenter @AssistedInject constructor( @Composable override fun present(): JoinRoomState { val roomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty()) - val joinAuthorisationStatus = joinAuthorisationStatus(roomInfo) - val acceptDeclineInviteState = acceptDeclineInvitePresenter.present() val contentState by produceState>(initialValue = AsyncData.Uninitialized, key1 = roomInfo) { value = when { roomInfo.isPresent -> { @@ -61,20 +59,25 @@ class JoinRoomPresenter @AssistedInject constructor( val contentState = roomDescription.get().toContentState() AsyncData.Success(contentState) } - else -> AsyncData.Uninitialized + else -> { + AsyncData.Uninitialized + } } } + val acceptDeclineInviteState = acceptDeclineInvitePresenter.present() fun handleEvents(event: JoinRoomEvents) { when (event) { JoinRoomEvents.AcceptInvite, JoinRoomEvents.JoinRoom -> { + val inviteData = contentState.toInviteData() ?: return acceptDeclineInviteState.eventSink( - AcceptDeclineInviteEvents.AcceptInvite(contentState.toInviteData()) + AcceptDeclineInviteEvents.AcceptInvite(inviteData) ) } JoinRoomEvents.DeclineInvite -> { + val inviteData = contentState.toInviteData() ?: return acceptDeclineInviteState.eventSink( - AcceptDeclineInviteEvents.DeclineInvite(contentState.toInviteData()) + AcceptDeclineInviteEvents.DeclineInvite(inviteData) ) } } @@ -82,66 +85,69 @@ class JoinRoomPresenter @AssistedInject constructor( return JoinRoomState( contentState = contentState, - joinAuthorisationStatus = joinAuthorisationStatus, acceptDeclineInviteState = acceptDeclineInviteState, eventSink = ::handleEvents ) } +} - private fun RoomDescription.toContentState(): ContentState { - return ContentState( - roomId = roomId, - name = name, - description = description, - numberOfMembers = numberOfMembers, - isDirect = false, - roomAvatarUrl = avatarUrl - ) - } - - private fun MatrixRoomInfo.toContentState(): ContentState { - fun title(): String { - return name ?: canonicalAlias ?: roomId.value - } - - fun description(): String? { - val topic = topic - val alias = canonicalAlias - val name = name - return when { - topic != null -> topic - name != null && alias != null -> alias - name == null && alias == null -> null - else -> roomId.value - } +@VisibleForTesting +internal fun RoomDescription.toContentState(): ContentState { + return ContentState( + roomId = roomId, + name = name, + description = description, + numberOfMembers = numberOfMembers, + isDirect = false, + roomAvatarUrl = avatarUrl, + joinAuthorisationStatus = when (joinRule) { + RoomDescription.JoinRule.KNOCK -> JoinAuthorisationStatus.CanKnock + RoomDescription.JoinRule.PUBLIC -> JoinAuthorisationStatus.CanJoin + else -> JoinAuthorisationStatus.Unknown } + ) +} - return ContentState( - roomId = roomId, - name = title(), - description = description(), - numberOfMembers = activeMembersCount, - isDirect = isDirect, - roomAvatarUrl = avatarUrl - ) +@VisibleForTesting +internal fun MatrixRoomInfo.toContentState(): ContentState { + fun title(): String { + return name ?: canonicalAlias ?: id } - private fun AsyncData.toInviteData(): InviteData { - return dataOrNull().let { - InviteData( - roomId = roomId, - roomName = it?.name ?: "", - isDirect = it?.isDirect ?: false - ) + fun description(): String? { + val topic = topic + val alias = canonicalAlias + val name = name + return when { + topic != null -> topic + name != null && alias != null -> alias + name == null && alias == null -> null + else -> id } } - @Composable - private fun joinAuthorisationStatus(roomInfo: Optional): JoinAuthorisationStatus { - val userMembership = roomInfo.getOrNull()?.currentUserMembership - return when { - userMembership == CurrentUserMembership.INVITED -> return JoinAuthorisationStatus.IsInvited + return ContentState( + roomId = RoomId(id), + name = title(), + description = description(), + numberOfMembers = activeMembersCount, + isDirect = isDirect, + roomAvatarUrl = avatarUrl, + joinAuthorisationStatus = when { + currentUserMembership == CurrentUserMembership.INVITED -> JoinAuthorisationStatus.IsInvited + isPublic -> JoinAuthorisationStatus.CanJoin else -> JoinAuthorisationStatus.Unknown } + ) +} + +@VisibleForTesting +internal fun AsyncData.toInviteData(): InviteData? { + return dataOrNull()?.let { contentState -> + InviteData( + roomId = contentState.roomId, + roomName = contentState.name, + isDirect = contentState.isDirect + ) } } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt index 73218bf7ba..c8211feb0d 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -26,10 +26,11 @@ import io.element.android.libraries.matrix.api.core.RoomId @Immutable data class JoinRoomState( val contentState: AsyncData, - val joinAuthorisationStatus: JoinAuthorisationStatus, val acceptDeclineInviteState: AcceptDeclineInviteState, val eventSink: (JoinRoomEvents) -> Unit -) +) { + val joinAuthorisationStatus = contentState.dataOrNull()?.joinAuthorisationStatus ?: JoinAuthorisationStatus.Unknown +} data class ContentState( val roomId: RoomId, @@ -38,6 +39,7 @@ data class ContentState( val numberOfMembers: Long?, val isDirect: Boolean, val roomAvatarUrl: String?, + val joinAuthorisationStatus: JoinAuthorisationStatus, ) { val showMemberCount = numberOfMembers != null diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index a1c77a7de2..994f914a19 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -29,34 +29,49 @@ open class JoinRoomStateProvider : PreviewParameterProvider { contentState = AsyncData.Uninitialized ), aJoinRoomState( - joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin + contentState = AsyncData.Success( + aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin) + ) ), aJoinRoomState( - joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock + contentState = AsyncData.Success( + aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock) + ) ), aJoinRoomState( - joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited + contentState = AsyncData.Success( + aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited) + ) ), ) } +fun aContentState( + roomId: RoomId = RoomId("@exa:matrix.org"), + name: String = "Element x android", + description: String? = "#exa:matrix.org", + numberOfMembers: Long? = null, + isDirect: Boolean = false, + roomAvatarUrl: String? = null, + joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown +) = ContentState( + roomId = roomId, + name = name, + description = description, + numberOfMembers = numberOfMembers, + isDirect = isDirect, + roomAvatarUrl = roomAvatarUrl, + joinAuthorisationStatus = joinAuthorisationStatus +) + fun aJoinRoomState( contentState: AsyncData = AsyncData.Success( - ContentState( - roomId = RoomId("@exa:matrix.org"), - name = "Element x android", - description = "#exa:matrix.org", - numberOfMembers = null, - isDirect = false, - roomAvatarUrl = null - ) + aContentState() ), - joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown, acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(), eventSink: (JoinRoomEvents) -> Unit = {} ) = JoinRoomState( contentState = contentState, - joinAuthorisationStatus = joinAuthorisationStatus, acceptDeclineInviteState = acceptDeclineInviteState, eventSink = eventSink ) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index ca16b12880..5cef755af2 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -109,8 +109,7 @@ private fun JoinRoomFooter( ) } } - // TODO handle all cases properly - else -> { + JoinAuthorisationStatus.CanJoin -> { Button( text = stringResource(CommonStrings.action_join), onClick = onJoinRoom, @@ -118,6 +117,18 @@ private fun JoinRoomFooter( size = ButtonSize.Medium, ) } + JoinAuthorisationStatus.CanKnock -> { + //TODO knock + /* + Button( + text = stringResource(CommonStrings.action_knock), + onClick = onJoinRoom, + modifier = modifier.fillMaxWidth(), + size = ButtonSize.Medium, + ) + */ + } + JoinAuthorisationStatus.Unknown -> Unit } } @@ -154,8 +165,8 @@ private fun JoinRoomContent( Column( modifier = modifier - .fillMaxWidth() - .padding(all = 16.dp), + .fillMaxWidth() + .padding(all = 16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { when (asyncContentState) { @@ -191,9 +202,9 @@ private fun JoinRoomMembersCount(memberCount: Long) { Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier - .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) - .widthIn(min = 48.dp) - .padding(all = 2.dp), + .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) + .widthIn(min = 48.dp) + .padding(all = 2.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp) ) { 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 new file mode 100644 index 0000000000..45dc4361c5 --- /dev/null +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.joinroom.impl + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents +import io.element.android.features.invite.api.response.AcceptDeclineInviteState +import io.element.android.features.invite.api.response.anAcceptDeclineInviteState +import io.element.android.features.roomdirectory.api.RoomDescription +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_NAME +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.assert +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value +import io.element.android.tests.testutils.test +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test +import java.util.Optional + +class JoinRoomPresenterTest { + + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `present - initial state`() = runTest { + val presenter = createJoinRoomPresenter() + presenter.test { + awaitItem().also { state -> + assertThat(state.contentState).isInstanceOf(AsyncData.Uninitialized::class.java) + assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown) + assertThat(state.acceptDeclineInviteState).isEqualTo(anAcceptDeclineInviteState()) + } + } + } + + @Test + fun `present - when room is joined then content state is filled with his data`() = runTest { + val roomInfo = aRoomInfo() + val matrixClient = FakeMatrixClient().apply { + getRoomInfoFlowLambda = { _ -> + flowOf(Optional.of(roomInfo)) + } + } + val presenter = createJoinRoomPresenter( + matrixClient = matrixClient + ) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.contentState).isInstanceOf(AsyncData.Success::class.java) + val contentState = state.contentState.dataOrNull()!! + assertThat(contentState.roomId).isEqualTo(A_ROOM_ID) + assertThat(contentState.name).isEqualTo(roomInfo.name) + assertThat(contentState.description).isEqualTo(roomInfo.topic) + assertThat(contentState.numberOfMembers).isEqualTo(roomInfo.activeMembersCount) + assertThat(contentState.isDirect).isEqualTo(roomInfo.isDirect) + assertThat(contentState.roomAvatarUrl).isEqualTo(roomInfo.avatarUrl) + } + } + } + + @Test + fun `present - when room is invited then join authorization is equal to invited`() = runTest { + val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED) + val matrixClient = FakeMatrixClient().apply { + getRoomInfoFlowLambda = { _ -> + flowOf(Optional.of(roomInfo)) + } + } + val presenter = createJoinRoomPresenter( + matrixClient = matrixClient + ) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.IsInvited) + } + } + } + + @Test + fun `present - when room is invited then accept and decline events are sent to acceptDeclinePresenter`() = runTest { + val eventSinkRecorder = lambdaRecorder { _: AcceptDeclineInviteEvents -> } + val acceptDeclinePresenter = Presenter { + anAcceptDeclineInviteState(eventSink = eventSinkRecorder) + } + val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED) + val matrixClient = FakeMatrixClient().apply { + getRoomInfoFlowLambda = { _ -> + flowOf(Optional.of(roomInfo)) + } + } + val presenter = createJoinRoomPresenter( + matrixClient = matrixClient, + acceptDeclineInvitePresenter = acceptDeclinePresenter + ) + presenter.test { + skipItems(1) + + awaitItem().also { state -> + state.eventSink(JoinRoomEvents.AcceptInvite) + state.eventSink(JoinRoomEvents.DeclineInvite) + + val inviteData = state.contentState.toInviteData()!! + + assert(eventSinkRecorder) + .isCalledExactly(2) + .withSequence( + listOf(value(AcceptDeclineInviteEvents.AcceptInvite(inviteData))), + listOf(value(AcceptDeclineInviteEvents.DeclineInvite(inviteData))), + ) + + } + } + } + + @Test + fun `present - when room is left and public then join authorization is equal to canJoin`() = runTest { + val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.LEFT, isPublic = true) + val matrixClient = FakeMatrixClient().apply { + getRoomInfoFlowLambda = { _ -> + flowOf(Optional.of(roomInfo)) + } + } + val presenter = createJoinRoomPresenter( + matrixClient = matrixClient + ) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.CanJoin) + } + } + } + + @Test + fun `present - when room is left and not public then join authorization is equal to unknown`() = runTest { + val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.LEFT, isPublic = false) + val matrixClient = FakeMatrixClient().apply { + getRoomInfoFlowLambda = { _ -> + flowOf(Optional.of(roomInfo)) + } + } + val presenter = createJoinRoomPresenter( + matrixClient = matrixClient + ) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown) + } + } + } + + @Test + fun `present - when room description is provided and room is not found then content state is filled with data`() = runTest { + val roomDescription = aRoomDescription() + val presenter = createJoinRoomPresenter( + roomDescription = Optional.of(roomDescription) + ) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.contentState).isInstanceOf(AsyncData.Success::class.java) + val contentState = state.contentState.dataOrNull()!! + assertThat(contentState.roomId).isEqualTo(A_ROOM_ID) + assertThat(contentState.name).isEqualTo(roomDescription.name) + assertThat(contentState.description).isEqualTo(roomDescription.description) + assertThat(contentState.numberOfMembers).isEqualTo(roomDescription.numberOfMembers) + assertThat(contentState.isDirect).isFalse() + assertThat(contentState.roomAvatarUrl).isEqualTo(roomDescription.avatarUrl) + } + } + } + + @Test + fun `present - when room description join rule is Knock then join authorization is equal to canKnock`() = runTest { + val roomDescription = aRoomDescription(joinRule = RoomDescription.JoinRule.KNOCK) + val presenter = createJoinRoomPresenter( + roomDescription = Optional.of(roomDescription) + ) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.CanKnock) + } + } + } + + @Test + fun `present - when room description join rule is Public then join authorization is equal to canJoin`() = runTest { + val roomDescription = aRoomDescription(joinRule = RoomDescription.JoinRule.PUBLIC) + val presenter = createJoinRoomPresenter( + roomDescription = Optional.of(roomDescription) + ) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.CanJoin) + } + } + } + + @Test + fun `present - when room description join rule is Unknown then join authorization is equal to unknown`() = runTest { + val roomDescription = aRoomDescription(joinRule = RoomDescription.JoinRule.UNKNOWN) + val presenter = createJoinRoomPresenter( + roomDescription = Optional.of(roomDescription) + ) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown) + } + } + } + + private fun createJoinRoomPresenter( + roomId: RoomId = A_ROOM_ID, + roomDescription: Optional = Optional.empty(), + matrixClient: MatrixClient = FakeMatrixClient(), + acceptDeclineInvitePresenter: Presenter = Presenter { anAcceptDeclineInviteState() } + ): JoinRoomPresenter { + return JoinRoomPresenter( + roomId = roomId, + roomDescription = roomDescription, + matrixClient = matrixClient, + acceptDeclineInvitePresenter = acceptDeclineInvitePresenter + ) + } + + private fun aRoomDescription( + roomId: RoomId = A_ROOM_ID, + name: String = A_ROOM_NAME, + description: String = "A room about something", + avatarUrl: String? = null, + joinRule: RoomDescription.JoinRule = RoomDescription.JoinRule.UNKNOWN, + numberOfMembers: Long = 2L + ): RoomDescription { + return RoomDescription( + roomId = roomId, + name = name, + description = description, + avatarUrl = avatarUrl, + joinRule = joinRule, + numberOfMembers = numberOfMembers + ) + } +} diff --git a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt index bc0e9f48c1..a0a0e45a54 100644 --- a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt +++ b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt @@ -28,10 +28,18 @@ data class RoomDescription( val name: String, val description: String, val avatarUrl: String?, - val canBeJoined: Boolean, + val joinRule: JoinRule, val numberOfMembers: Long, ) : Parcelable { + enum class JoinRule { + PUBLIC, + KNOCK, + UNKNOWN + } + + fun canBeJoined() = joinRule == JoinRule.PUBLIC || joinRule == JoinRule.KNOCK + fun avatarData(size: AvatarSize) = AvatarData( id = roomId.value, name = name, diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt index 3178a06322..ccfdd4c1f1 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt @@ -70,7 +70,7 @@ fun aRoomDescriptionList(): ImmutableList { name = "Element X Android", description = "Element X is a secure, private and decentralized messenger.", avatarUrl = null, - canBeJoined = true, + joinRule = RoomDescription.JoinRule.PUBLIC, numberOfMembers = 2765, ), RoomDescription( @@ -78,7 +78,7 @@ fun aRoomDescriptionList(): ImmutableList { name = "Element X iOS", description = "Element X is a secure, private and decentralized messenger.", avatarUrl = null, - canBeJoined = false, + joinRule = RoomDescription.JoinRule.UNKNOWN, numberOfMembers = 356, ) ) diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt index 6fe326bfb6..f1ea915c17 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt @@ -274,7 +274,7 @@ private fun RoomDirectoryRoomRow( Row( modifier = modifier .fillMaxWidth() - .clickable(enabled = roomDescription.canBeJoined, onClick = onClick) + .clickable(onClick = onClick) .padding( top = 12.dp, bottom = 12.dp, @@ -306,7 +306,7 @@ private fun RoomDirectoryRoomRow( overflow = TextOverflow.Ellipsis, ) } - if (roomDescription.canBeJoined) { + if (roomDescription.canBeJoined()) { Text( text = stringResource(id = CommonStrings.action_join), color = ElementTheme.colors.textSuccessPrimary, diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt index 5ace7645aa..eec9f6acf9 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt @@ -44,6 +44,10 @@ fun MatrixRoomDescription.toFeatureModel(): RoomDescription { description = description(), avatarUrl = avatarUrl, numberOfMembers = numberOfMembers, - canBeJoined = joinRule == MatrixRoomDescription.JoinRule.PUBLIC, + joinRule = when (joinRule) { + MatrixRoomDescription.JoinRule.PUBLIC -> RoomDescription.JoinRule.PUBLIC + MatrixRoomDescription.JoinRule.KNOCK -> RoomDescription.JoinRule.KNOCK + MatrixRoomDescription.JoinRule.UNKNOWN -> RoomDescription.JoinRule.UNKNOWN + } ) } From 8fca9d71626402697d3a91c92cb3f4354eafb310 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 22:44:09 +0000 Subject: [PATCH 17/52] Update dependency com.google.firebase:firebase-bom to v32.8.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8f78a929be..77cde5cb89 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -63,7 +63,7 @@ kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", v kover_gradle_plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" } gms_google_services = "com.google.gms:google-services:4.4.1" # https://firebase.google.com/docs/android/setup#available-libraries -google_firebase_bom = "com.google.firebase:firebase-bom:32.8.0" +google_firebase_bom = "com.google.firebase:firebase-bom:32.8.1" firebase_appdistribution_gradle = { module = "com.google.firebase:firebase-appdistribution-gradle", version.ref = "firebaseAppDistribution" } autonomousapps_dependencyanalysis_plugin = { module = "com.autonomousapps:dependency-analysis-gradle-plugin", version.ref = "dependencyAnalysis" } From a2329fc7df3ed033de6117c38d79a0be78f17bd1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Apr 2024 14:09:57 +0200 Subject: [PATCH 18/52] Join room : change state and view --- .../joinroom/impl/JoinRoomPresenter.kt | 52 ++---- .../features/joinroom/impl/JoinRoomState.kt | 54 +++--- .../joinroom/impl/JoinRoomStateProvider.kt | 36 ++-- .../features/joinroom/impl/JoinRoomView.kt | 165 ++++++++++++------ .../joinroom/impl/JoinRoomPresenterTest.kt | 26 +-- .../roomdirectory/api/RoomDescription.kt | 19 +- .../impl/root/RoomDirectoryStateProvider.kt | 6 +- .../impl/root/RoomDirectoryView.kt | 4 +- .../impl/root/model/RoomDescription.kt | 22 +-- .../atomic/pages/HeaderFooterPage.kt | 4 +- .../matrix/impl/util/CallbackFlow.kt | 5 +- 11 files changed, 228 insertions(+), 165 deletions(-) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt index 777de024c5..26b661b3eb 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 @@ -26,7 +26,6 @@ import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.InviteData import io.element.android.features.roomdirectory.api.RoomDescription -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -49,18 +48,16 @@ class JoinRoomPresenter @AssistedInject constructor( @Composable override fun present(): JoinRoomState { val roomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty()) - val contentState by produceState>(initialValue = AsyncData.Uninitialized, key1 = roomInfo) { + val contentState by produceState(initialValue = ContentState.Loading(roomId), key1 = roomInfo) { value = when { roomInfo.isPresent -> { - val contentState = roomInfo.get().toContentState() - AsyncData.Success(contentState) + roomInfo.get().toContentState() } roomDescription.isPresent -> { - val contentState = roomDescription.get().toContentState() - AsyncData.Success(contentState) + roomDescription.get().toContentState() } else -> { - AsyncData.Uninitialized + ContentState.UnknownRoom(roomId) } } } @@ -93,10 +90,11 @@ class JoinRoomPresenter @AssistedInject constructor( @VisibleForTesting internal fun RoomDescription.toContentState(): ContentState { - return ContentState( + return ContentState.Loaded( roomId = roomId, name = name, - description = description, + topic = topic, + alias = alias, numberOfMembers = numberOfMembers, isDirect = false, roomAvatarUrl = avatarUrl, @@ -110,26 +108,11 @@ internal fun RoomDescription.toContentState(): ContentState { @VisibleForTesting internal fun MatrixRoomInfo.toContentState(): ContentState { - fun title(): String { - return name ?: canonicalAlias ?: id - } - - fun description(): String? { - val topic = topic - val alias = canonicalAlias - val name = name - return when { - topic != null -> topic - name != null && alias != null -> alias - name == null && alias == null -> null - else -> id - } - } - - return ContentState( + return ContentState.Loaded( roomId = RoomId(id), - name = title(), - description = description(), + name = name, + topic = topic, + alias = canonicalAlias, numberOfMembers = activeMembersCount, isDirect = isDirect, roomAvatarUrl = avatarUrl, @@ -142,12 +125,13 @@ internal fun MatrixRoomInfo.toContentState(): ContentState { } @VisibleForTesting -internal fun AsyncData.toInviteData(): InviteData? { - return dataOrNull()?.let { contentState -> - InviteData( - roomId = contentState.roomId, - roomName = contentState.name, - isDirect = contentState.isDirect +internal fun ContentState.toInviteData(): InviteData? { + return when (this) { + is ContentState.Loaded -> InviteData( + roomId = roomId, + roomName = computedTitle, + isDirect = isDirect ) + else -> null } } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt index c8211feb0d..01647e1fdd 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -18,39 +18,53 @@ package io.element.android.features.joinroom.impl import androidx.compose.runtime.Immutable import io.element.android.features.invite.api.response.AcceptDeclineInviteState -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomId @Immutable data class JoinRoomState( - val contentState: AsyncData, + val contentState: ContentState, val acceptDeclineInviteState: AcceptDeclineInviteState, val eventSink: (JoinRoomEvents) -> Unit ) { - val joinAuthorisationStatus = contentState.dataOrNull()?.joinAuthorisationStatus ?: JoinAuthorisationStatus.Unknown + val joinAuthorisationStatus = when(contentState) { + is ContentState.Loaded -> contentState.joinAuthorisationStatus + else -> JoinAuthorisationStatus.Unknown + } } -data class ContentState( - val roomId: RoomId, - val name: String, - val description: String?, - val numberOfMembers: Long?, - val isDirect: Boolean, - val roomAvatarUrl: String?, - val joinAuthorisationStatus: JoinAuthorisationStatus, -) { +sealed interface ContentState { + data class Loading(val roomId: RoomId) : ContentState + data class UnknownRoom(val roomId: RoomId) : ContentState + data class Loaded( + val roomId: RoomId, + val name: String?, + val topic: String?, + val alias: String?, + val numberOfMembers: Long?, + val isDirect: Boolean, + val roomAvatarUrl: String?, + val joinAuthorisationStatus: JoinAuthorisationStatus, + ) : ContentState { + val computedTitle = name ?: roomId.value + + val computedSubtitle = when { + alias != null -> alias + name == null -> "" + else -> roomId.value + } - val showMemberCount = numberOfMembers != null + val showMemberCount = numberOfMembers != null - fun avatarData(size: AvatarSize): AvatarData { - return AvatarData( - id = roomId.value, - name = name, - url = roomAvatarUrl, - size = size, - ) + fun avatarData(size: AvatarSize): AvatarData { + return AvatarData( + id = roomId.value, + name = name, + url = roomAvatarUrl, + size = size, + ) + } } } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 994f914a19..5e10613557 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -19,45 +19,47 @@ package io.element.android.features.joinroom.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.anAcceptDeclineInviteState -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.RoomId open class JoinRoomStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aJoinRoomState( - contentState = AsyncData.Uninitialized + contentState = anUninitializedContentState() ), aJoinRoomState( - contentState = AsyncData.Success( - aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin) - ) + contentState = anUnknownContentState() ), aJoinRoomState( - contentState = AsyncData.Success( - aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock) - ) + contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin) ), aJoinRoomState( - contentState = AsyncData.Success( - aContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited) - ) + contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock) + ), + aJoinRoomState( + contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited) ), ) } -fun aContentState( +fun anUnknownContentState(roomId: RoomId = RoomId("@exa:matrix.org")) = ContentState.UnknownRoom(roomId) + +fun anUninitializedContentState(roomId: RoomId = RoomId("@exa:matrix.org")) = ContentState.Loading(roomId) + +fun aLoadedContentState( roomId: RoomId = RoomId("@exa:matrix.org"), name: String = "Element x android", - description: String? = "#exa:matrix.org", + alias: String? = "#exa:matrix.org", + topic: String? = "Element X is a secure, private and decentralized messenger.", numberOfMembers: Long? = null, isDirect: Boolean = false, roomAvatarUrl: String? = null, joinAuthorisationStatus: JoinAuthorisationStatus = JoinAuthorisationStatus.Unknown -) = ContentState( +) = ContentState.Loaded( roomId = roomId, name = name, - description = description, + alias = alias, + topic = topic, numberOfMembers = numberOfMembers, isDirect = isDirect, roomAvatarUrl = roomAvatarUrl, @@ -65,9 +67,7 @@ fun aContentState( ) fun aJoinRoomState( - contentState: AsyncData = AsyncData.Success( - aContentState() - ), + contentState: ContentState = aLoadedContentState(), acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(), eventSink: (JoinRoomEvents) -> Unit = {} ) = JoinRoomState( diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 5cef755af2..3ac19b5daf 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -16,9 +16,11 @@ package io.element.android.features.joinroom.impl +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -30,14 +32,15 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom import io.element.android.libraries.designsystem.atomic.molecules.ButtonRowMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage @@ -61,11 +64,12 @@ fun JoinRoomView( ) { HeaderFooterPage( modifier = modifier, + paddingValues = PaddingValues(16.dp), topBar = { JoinRoomTopBar(onBackClicked = onBackPressed) }, content = { - JoinRoomContent(asyncContentState = state.contentState) + JoinRoomContent(contentState = state.contentState) }, footer = { JoinRoomFooter( @@ -111,22 +115,19 @@ private fun JoinRoomFooter( } JoinAuthorisationStatus.CanJoin -> { Button( - text = stringResource(CommonStrings.action_join), + text = stringResource(R.string.screen_join_room_join_action), onClick = onJoinRoom, modifier = modifier.fillMaxWidth(), size = ButtonSize.Medium, ) } JoinAuthorisationStatus.CanKnock -> { - //TODO knock - /* Button( - text = stringResource(CommonStrings.action_knock), + text = stringResource(R.string.screen_join_room_knock_action), onClick = onJoinRoom, modifier = modifier.fillMaxWidth(), size = ButtonSize.Medium, ) - */ } JoinAuthorisationStatus.Unknown -> Unit } @@ -134,63 +135,60 @@ private fun JoinRoomFooter( @Composable private fun JoinRoomContent( - asyncContentState: AsyncData, + contentState: ContentState, modifier: Modifier = Modifier, ) { - @Composable - fun ContentScaffold( - avatar: @Composable () -> Unit, - title: String, - description: String, - memberCount: @Composable (() -> Unit)? = null - ) { - avatar() - Spacer(modifier = Modifier.height(16.dp)) - Text( - text = title, - style = ElementTheme.typography.fontHeadingMdBold, - textAlign = TextAlign.Center, - color = ElementTheme.colors.textPrimary, - ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = description, - style = ElementTheme.typography.fontBodyMdRegular, - textAlign = TextAlign.Center, - color = ElementTheme.colors.textSecondary, - ) - memberCount?.invoke() - } - Column( - modifier = modifier - .fillMaxWidth() - .padding(all = 16.dp), + modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { - when (asyncContentState) { - is AsyncData.Success -> { - val contentState = asyncContentState.data + when (contentState) { + is ContentState.Loaded -> { ContentScaffold( avatar = { Avatar(contentState.avatarData(AvatarSize.RoomHeader)) }, - title = contentState.name, - description = contentState.description ?: stringResource(R.string.screen_join_room_subtitle_no_preview) - ) { - if (contentState.showMemberCount) { - JoinRoomMembersCount(memberCount = contentState.numberOfMembers ?: 0) + title = { + Title(contentState.computedTitle) + }, + subtitle = { + Subtitle(contentState.computedSubtitle) + }, + description = { + Description(contentState.topic ?: "") + }, + memberCount = { + if (contentState.showMemberCount) { + MembersCount(memberCount = contentState.numberOfMembers ?: 0) + } } - } + ) } - else -> { + is ContentState.UnknownRoom -> { ContentScaffold( avatar = { PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) }, - title = stringResource(R.string.screen_join_room_title_no_preview), - description = stringResource(R.string.screen_join_room_subtitle_no_preview), + title = { + Title(stringResource(R.string.screen_join_room_title_no_preview)) + }, + subtitle = { + Subtitle(stringResource(R.string.screen_join_room_subtitle_no_preview)) + }, + ) + } + is ContentState.Loading -> { + ContentScaffold( + avatar = { + PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) + }, + title = { + PlaceholderAtom(width = 200.dp, height = 22.dp) + }, + subtitle = { + PlaceholderAtom(width = 140.dp, height = 20.dp) + }, ) } } @@ -198,13 +196,72 @@ private fun JoinRoomContent( } @Composable -private fun JoinRoomMembersCount(memberCount: Long) { +private fun ContentScaffold( + avatar: @Composable () -> Unit, + title: @Composable () -> Unit, + subtitle: @Composable () -> Unit, + description: @Composable (() -> Unit)? = null, + memberCount: @Composable (() -> Unit)? = null, +) { + avatar() + Spacer(modifier = Modifier.height(16.dp)) + title() + Spacer(modifier = Modifier.height(8.dp)) + subtitle() + Spacer(modifier = Modifier.height(8.dp)) + if (memberCount != null) { + memberCount() + } + Spacer(modifier = Modifier.height(8.dp)) + if (description != null) { + description() + } + Spacer(modifier = Modifier.height(24.dp)) +} + +@Composable +private fun Title(title: String, modifier: Modifier = Modifier) { + Text( + modifier = modifier, + text = title, + style = ElementTheme.typography.fontHeadingMdBold, + textAlign = TextAlign.Center, + color = ElementTheme.colors.textPrimary, + ) +} + +@Composable +private fun Subtitle(subtitle: String, modifier: Modifier = Modifier) { + Text( + modifier = modifier, + text = subtitle, + style = ElementTheme.typography.fontBodyLgRegular, + textAlign = TextAlign.Center, + color = ElementTheme.colors.textSecondary, + ) +} + +@Composable +private fun Description(description: String, modifier: Modifier = Modifier) { + Text( + modifier = modifier, + text = description, + style = ElementTheme.typography.fontBodySmRegular, + textAlign = TextAlign.Center, + color = ElementTheme.colors.textSecondary, + maxLines = 3, + overflow = TextOverflow.Ellipsis, + ) +} + +@Composable +private fun MembersCount(memberCount: Long) { Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier - .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) - .widthIn(min = 48.dp) - .padding(all = 2.dp), + .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) + .widthIn(min = 48.dp) + .padding(all = 2.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp) ) { @@ -230,9 +287,7 @@ private fun JoinRoomTopBar( navigationIcon = { BackButton(onClick = onBackClicked) }, - title = { - - }, + title = {}, ) } 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 45dc4361c5..19cc23c995 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 @@ -21,7 +21,6 @@ import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.anAcceptDeclineInviteState import io.element.android.features.roomdirectory.api.RoomDescription -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -51,10 +50,13 @@ class JoinRoomPresenterTest { val presenter = createJoinRoomPresenter() presenter.test { awaitItem().also { state -> - assertThat(state.contentState).isInstanceOf(AsyncData.Uninitialized::class.java) + assertThat(state.contentState).isEqualTo(ContentState.Loading(A_ROOM_ID)) assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown) assertThat(state.acceptDeclineInviteState).isEqualTo(anAcceptDeclineInviteState()) } + awaitItem().also { state -> + assertThat(state.contentState).isEqualTo(ContentState.UnknownRoom(A_ROOM_ID)) + } } } @@ -72,11 +74,11 @@ class JoinRoomPresenterTest { presenter.test { skipItems(1) awaitItem().also { state -> - assertThat(state.contentState).isInstanceOf(AsyncData.Success::class.java) - val contentState = state.contentState.dataOrNull()!! + val contentState = state.contentState as ContentState.Loaded assertThat(contentState.roomId).isEqualTo(A_ROOM_ID) assertThat(contentState.name).isEqualTo(roomInfo.name) - assertThat(contentState.description).isEqualTo(roomInfo.topic) + assertThat(contentState.topic).isEqualTo(roomInfo.topic) + assertThat(contentState.alias).isEqualTo(roomInfo.canonicalAlias) assertThat(contentState.numberOfMembers).isEqualTo(roomInfo.activeMembersCount) assertThat(contentState.isDirect).isEqualTo(roomInfo.isDirect) assertThat(contentState.roomAvatarUrl).isEqualTo(roomInfo.avatarUrl) @@ -186,11 +188,11 @@ class JoinRoomPresenterTest { presenter.test { skipItems(1) awaitItem().also { state -> - assertThat(state.contentState).isInstanceOf(AsyncData.Success::class.java) - val contentState = state.contentState.dataOrNull()!! + val contentState = state.contentState as ContentState.Loaded assertThat(contentState.roomId).isEqualTo(A_ROOM_ID) assertThat(contentState.name).isEqualTo(roomDescription.name) - assertThat(contentState.description).isEqualTo(roomDescription.description) + assertThat(contentState.topic).isEqualTo(roomDescription.topic) + assertThat(contentState.alias).isEqualTo(roomDescription.alias) assertThat(contentState.numberOfMembers).isEqualTo(roomDescription.numberOfMembers) assertThat(contentState.isDirect).isFalse() assertThat(contentState.roomAvatarUrl).isEqualTo(roomDescription.avatarUrl) @@ -256,8 +258,9 @@ class JoinRoomPresenterTest { private fun aRoomDescription( roomId: RoomId = A_ROOM_ID, - name: String = A_ROOM_NAME, - description: String = "A room about something", + name: String? = A_ROOM_NAME, + topic: String? = "A room about something", + alias: String? = "#alias:matrix.org", avatarUrl: String? = null, joinRule: RoomDescription.JoinRule = RoomDescription.JoinRule.UNKNOWN, numberOfMembers: Long = 2L @@ -265,7 +268,8 @@ class JoinRoomPresenterTest { return RoomDescription( roomId = roomId, name = name, - description = description, + topic = topic, + alias = alias, avatarUrl = avatarUrl, joinRule = joinRule, numberOfMembers = numberOfMembers diff --git a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt index a0a0e45a54..632173100a 100644 --- a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt +++ b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt @@ -17,16 +17,19 @@ package io.element.android.features.roomdirectory.api import android.os.Parcelable +import androidx.compose.runtime.Immutable import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomId import kotlinx.parcelize.Parcelize @Parcelize +@Immutable data class RoomDescription( val roomId: RoomId, - val name: String, - val description: String, + val name: String?, + val alias: String?, + val topic: String?, val avatarUrl: String?, val joinRule: JoinRule, val numberOfMembers: Long, @@ -38,6 +41,18 @@ data class RoomDescription( UNKNOWN } + val computedName = name ?: alias ?: roomId.value + + val computedDescription: String + get() { + return when { + topic != null -> topic + name != null && alias != null -> alias + name == null && alias == null -> "" + else -> roomId.value + } + } + fun canBeJoined() = joinRule == JoinRule.PUBLIC || joinRule == JoinRule.KNOCK fun avatarData(size: AvatarSize) = AvatarData( diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt index ccfdd4c1f1..e94271cfb8 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryStateProvider.kt @@ -68,7 +68,8 @@ fun aRoomDescriptionList(): ImmutableList { RoomDescription( roomId = RoomId("!exa:matrix.org"), name = "Element X Android", - description = "Element X is a secure, private and decentralized messenger.", + topic = "Element X is a secure, private and decentralized messenger.", + alias = "#element-x-android:matrix.org", avatarUrl = null, joinRule = RoomDescription.JoinRule.PUBLIC, numberOfMembers = 2765, @@ -76,7 +77,8 @@ fun aRoomDescriptionList(): ImmutableList { RoomDescription( roomId = RoomId("!exi:matrix.org"), name = "Element X iOS", - description = "Element X is a secure, private and decentralized messenger.", + topic = "Element X is a secure, private and decentralized messenger.", + alias = "#element-x-ios:matrix.org", avatarUrl = null, joinRule = RoomDescription.JoinRule.UNKNOWN, numberOfMembers = 356, diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt index f1ea915c17..c8fe34e85e 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt @@ -292,14 +292,14 @@ private fun RoomDirectoryRoomRow( .padding(start = 16.dp) ) { Text( - text = roomDescription.name, + text = roomDescription.computedName, maxLines = 1, style = ElementTheme.typography.fontBodyLgRegular, color = ElementTheme.colors.textPrimary, overflow = TextOverflow.Ellipsis, ) Text( - text = roomDescription.description, + text = roomDescription.computedDescription, maxLines = 1, style = ElementTheme.typography.fontBodyMdRegular, color = ElementTheme.colors.textSecondary, diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt index eec9f6acf9..994f20dd16 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt @@ -17,31 +17,15 @@ package io.element.android.features.roomdirectory.impl.root.model import io.element.android.features.roomdirectory.api.RoomDescription -import io.element.android.libraries.designsystem.components.avatar.AvatarData -import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription as MatrixRoomDescription fun MatrixRoomDescription.toFeatureModel(): RoomDescription { - fun name(): String { - return name ?: alias ?: roomId.value - } - - fun description(): String { - val topic = topic - val alias = alias - val name = name - return when { - topic != null -> topic - name != null && alias != null -> alias - name == null && alias == null -> "" - else -> roomId.value - } - } return RoomDescription( roomId = roomId, - name = name(), - description = description(), + name = name, + alias = alias, + topic = topic, avatarUrl = avatarUrl, numberOfMembers = numberOfMembers, joinRule = when (joinRule) { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt index b2cf88b8bc..71dfecddb8 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt @@ -18,6 +18,7 @@ package io.element.android.libraries.designsystem.atomic.pages import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -43,6 +44,7 @@ import io.element.android.libraries.designsystem.theme.components.Text @Composable fun HeaderFooterPage( modifier: Modifier = Modifier, + paddingValues: PaddingValues = PaddingValues(20.dp), background: @Composable () -> Unit = {}, topBar: @Composable () -> Unit = {}, header: @Composable () -> Unit = {}, @@ -57,7 +59,7 @@ fun HeaderFooterPage( background() Column( modifier = Modifier - .padding(all = 20.dp) + .padding(paddingValues = paddingValues) .padding(padding) .consumeWindowInsets(padding) ) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt index fbf393e587..b17a2f8cf2 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.impl.util +import io.element.android.libraries.core.data.tryOrNull import kotlinx.coroutines.channels.ProducerScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow @@ -23,7 +24,9 @@ import org.matrix.rustcomponents.sdk.TaskHandle internal fun mxCallbackFlow(block: suspend ProducerScope.() -> TaskHandle?) = callbackFlow { - val taskHandle: TaskHandle? = block(this) + val taskHandle: TaskHandle? = tryOrNull { + block(this) + } awaitClose { taskHandle?.cancelAndDestroy() } From b2fdfbe10f4228cee92866407af7a7d57b54cf64 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Apr 2024 15:47:25 +0200 Subject: [PATCH 19/52] version++ --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 5489393e86..166fde2aab 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -56,7 +56,7 @@ private const val versionMinor = 4 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -private const val versionPatch = 9 +private const val versionPatch = 10 object Versions { val versionCode = 4_000_000 + versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch From 11979167c5672518399c3ab3ca5c0dadff8f2550 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Apr 2024 15:58:15 +0200 Subject: [PATCH 20/52] Room navigation : some clean up --- .../invitelist/InviteListStateProvider.kt | 5 +- .../response/AcceptDeclineInvitePresenter.kt | 4 - .../AcceptDeclineInviteViewWrapper.kt | 1 - .../InternalAcceptDeclineInviteEvents.kt | 2 +- .../invitelist/InviteListPresenterTests.kt | 9 -- .../AcceptDeclineInvitePresenterTest.kt | 1 - .../joinroom/api/JoinRoomEntryPoint.kt | 2 - features/joinroom/impl/build.gradle.kts | 1 - .../impl/DefaultJoinRoomEntryPoint.kt | 1 - .../features/joinroom/impl/JoinRoomEvents.kt | 2 +- .../features/joinroom/impl/JoinRoomNode.kt | 1 - .../joinroom/impl/JoinRoomPresenter.kt | 1 - .../features/joinroom/impl/JoinRoomState.kt | 2 +- .../joinroom/impl/JoinRoomStateProvider.kt | 1 - .../features/joinroom/impl/JoinRoomView.kt | 142 +++++++++--------- .../joinroom/impl/JoinRoomPresenterTest.kt | 2 - .../impl/LeaveRoomPresenterImplTest.kt | 4 +- .../actions/AndroidLocationActionsTest.kt | 2 - .../roomdirectory/api/RoomDescription.kt | 7 +- .../impl/root/RoomDirectoryNode.kt | 1 - .../impl/root/RoomDirectoryView.kt | 42 +++--- .../impl/root/model/RoomDescription.kt | 1 - .../impl/root/RoomDirectoryViewTest.kt | 6 +- .../atomic/pages/HeaderFooterPage.kt | 1 + .../libraries/matrix/api/MatrixClient.kt | 2 - .../matrix/api/roomlist/RoomListService.kt | 3 - .../libraries/matrix/test/FakeMatrixClient.kt | 1 - .../android/libraries/testtags/TestTags.kt | 2 +- 28 files changed, 107 insertions(+), 142 deletions(-) diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt index e796896745..9814b1b20d 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/invitelist/InviteListStateProvider.kt @@ -18,17 +18,16 @@ package io.element.android.features.invite.impl.invitelist import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.invite.api.response.AcceptDeclineInviteState -import io.element.android.features.invite.impl.model.InviteListInviteSummary -import io.element.android.features.invite.impl.model.InviteSender import io.element.android.features.invite.api.response.AcceptDeclineInviteStateProvider import io.element.android.features.invite.api.response.anAcceptDeclineInviteState +import io.element.android.features.invite.impl.model.InviteListInviteSummary +import io.element.android.features.invite.impl.model.InviteSender import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf open class InviteListStateProvider : PreviewParameterProvider { - private val acceptDeclineInviteStateProvider = AcceptDeclineInviteStateProvider() override val values: Sequence diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt index b452a53bd6..5f7e80b7b1 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt @@ -23,7 +23,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import com.squareup.anvil.annotations.ContributesBinding import im.vector.app.features.analytics.plan.JoinedRoom import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents import io.element.android.features.invite.api.response.AcceptDeclineInviteState @@ -32,7 +31,6 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.architecture.runUpdatingState -import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.push.api.notifications.NotificationDrawerManager @@ -49,10 +47,8 @@ class AcceptDeclineInvitePresenter @Inject constructor( private val analyticsService: AnalyticsService, private val notificationDrawerManager: NotificationDrawerManager, ) : Presenter { - @Composable override fun present(): AcceptDeclineInviteState { - val localCoroutineScope = rememberCoroutineScope() val acceptedAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } val declinedAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteViewWrapper.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteViewWrapper.kt index 575b401dc0..a86b220364 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteViewWrapper.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInviteViewWrapper.kt @@ -27,7 +27,6 @@ import javax.inject.Inject @ContributesBinding(SessionScope::class) class AcceptDeclineInviteViewWrapper @Inject constructor() : AcceptDeclineInviteView { - @Composable override fun Render( state: AcceptDeclineInviteState, diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/InternalAcceptDeclineInviteEvents.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/InternalAcceptDeclineInviteEvents.kt index e15cc9cff1..1ccf2ee34f 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/InternalAcceptDeclineInviteEvents.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/InternalAcceptDeclineInviteEvents.kt @@ -18,7 +18,7 @@ package io.element.android.features.invite.impl.response import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents -sealed interface InternalAcceptDeclineInviteEvents: AcceptDeclineInviteEvents { +sealed interface InternalAcceptDeclineInviteEvents : AcceptDeclineInviteEvents { data object ConfirmDeclineInvite : InternalAcceptDeclineInviteEvents data object CancelDeclineInvite : InternalAcceptDeclineInviteEvents data object DismissAcceptError : InternalAcceptDeclineInviteEvents diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenterTests.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenterTests.kt index 17dcf7d11b..c984e9c5fb 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenterTests.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/invitelist/InviteListPresenterTests.kt @@ -24,11 +24,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.anAcceptDeclineInviteState -import io.element.android.features.invite.impl.invitelist.InviteListEvents -import io.element.android.features.invite.impl.invitelist.InviteListPresenter -import io.element.android.features.invite.impl.invitelist.InviteListState import io.element.android.features.invite.test.FakeSeenInvitesStore -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -43,14 +39,9 @@ import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.FakeMatrixClient -import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService -import io.element.android.libraries.push.api.notifications.NotificationDrawerManager -import io.element.android.libraries.push.test.notifications.FakeNotificationDrawerManager -import io.element.android.services.analytics.api.AnalyticsService -import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest import org.junit.Rule diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt index 8d37656000..dfb330da59 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt @@ -40,7 +40,6 @@ import org.junit.Test import java.util.Optional class AcceptDeclineInvitePresenterTest { - @get:Rule val warmUpRule = WarmUpRule() diff --git a/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt b/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt index 0047eb10a8..60f49b9d36 100644 --- a/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt +++ b/features/joinroom/api/src/main/kotlin/io/element/android/features/joinroom/api/JoinRoomEntryPoint.kt @@ -25,7 +25,6 @@ import io.element.android.libraries.matrix.api.core.RoomId import java.util.Optional interface JoinRoomEntryPoint : FeatureEntryPoint { - fun createNode(parentNode: Node, buildContext: BuildContext, inputs: Inputs): Node data class Inputs( @@ -33,4 +32,3 @@ interface JoinRoomEntryPoint : FeatureEntryPoint { val roomDescription: Optional, ) : NodeInputs } - diff --git a/features/joinroom/impl/build.gradle.kts b/features/joinroom/impl/build.gradle.kts index 00095d1401..b87410ec87 100644 --- a/features/joinroom/impl/build.gradle.kts +++ b/features/joinroom/impl/build.gradle.kts @@ -43,7 +43,6 @@ dependencies { implementation(projects.features.roomdirectory.api) implementation(projects.libraries.uiStrings) - testImplementation(libs.test.junit) testImplementation(libs.coroutines.test) testImplementation(libs.molecule.runtime) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPoint.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPoint.kt index ab2745a63f..05db8f1cb1 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPoint.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPoint.kt @@ -26,7 +26,6 @@ import javax.inject.Inject @ContributesBinding(AppScope::class) class DefaultJoinRoomEntryPoint @Inject constructor() : JoinRoomEntryPoint { - override fun createNode(parentNode: Node, buildContext: BuildContext, inputs: JoinRoomEntryPoint.Inputs): Node { return parentNode.createNode( buildContext = buildContext, diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt index e3dc73f505..999030cd50 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt @@ -17,7 +17,7 @@ package io.element.android.features.joinroom.impl sealed interface JoinRoomEvents { - data object JoinRoom: JoinRoomEvents + data object JoinRoom : JoinRoomEvents data object AcceptInvite : JoinRoomEvents data object DeclineInvite : JoinRoomEvents } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt index 7763c17cad..eaa195d88d 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt @@ -36,7 +36,6 @@ class JoinRoomNode @AssistedInject constructor( presenterFactory: JoinRoomPresenter.Factory, private val acceptDeclineInviteView: AcceptDeclineInviteView, ) : Node(buildContext, plugins = plugins) { - private val inputs: JoinRoomEntryPoint.Inputs = inputs() private val presenter = presenterFactory.create(inputs.roomId, inputs.roomDescription) 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 26b661b3eb..6bcb09b4c9 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 @@ -40,7 +40,6 @@ class JoinRoomPresenter @AssistedInject constructor( private val matrixClient: MatrixClient, private val acceptDeclineInvitePresenter: Presenter, ) : Presenter { - interface Factory { fun create(roomId: RoomId, roomDescription: Optional): JoinRoomPresenter } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt index 01647e1fdd..08591c068e 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -28,7 +28,7 @@ data class JoinRoomState( val acceptDeclineInviteState: AcceptDeclineInviteState, val eventSink: (JoinRoomEvents) -> Unit ) { - val joinAuthorisationStatus = when(contentState) { + val joinAuthorisationStatus = when (contentState) { is ContentState.Loaded -> contentState.joinAuthorisationStatus else -> JoinAuthorisationStatus.Unknown } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 5e10613557..0982980204 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -75,4 +75,3 @@ fun aJoinRoomState( acceptDeclineInviteState = acceptDeclineInviteState, eventSink = eventSink ) - diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 3ac19b5daf..3176924c9a 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -16,7 +16,6 @@ package io.element.android.features.joinroom.impl -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -32,7 +31,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow @@ -138,59 +136,56 @@ private fun JoinRoomContent( contentState: ContentState, modifier: Modifier = Modifier, ) { - - Column( - modifier = modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - when (contentState) { - is ContentState.Loaded -> { - ContentScaffold( - avatar = { - Avatar(contentState.avatarData(AvatarSize.RoomHeader)) - }, - title = { - Title(contentState.computedTitle) - }, - subtitle = { - Subtitle(contentState.computedSubtitle) - }, - description = { - Description(contentState.topic ?: "") - }, - memberCount = { - if (contentState.showMemberCount) { - MembersCount(memberCount = contentState.numberOfMembers ?: 0) - } + when (contentState) { + is ContentState.Loaded -> { + ContentScaffold( + modifier = modifier, + avatar = { + Avatar(contentState.avatarData(AvatarSize.RoomHeader)) + }, + title = { + Title(contentState.computedTitle) + }, + subtitle = { + Subtitle(contentState.computedSubtitle) + }, + description = { + Description(contentState.topic ?: "") + }, + memberCount = { + if (contentState.showMemberCount) { + MembersCount(memberCount = contentState.numberOfMembers ?: 0) } - ) - } - is ContentState.UnknownRoom -> { - ContentScaffold( - avatar = { - PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) - }, - title = { - Title(stringResource(R.string.screen_join_room_title_no_preview)) - }, - subtitle = { - Subtitle(stringResource(R.string.screen_join_room_subtitle_no_preview)) - }, - ) - } - is ContentState.Loading -> { - ContentScaffold( - avatar = { - PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) - }, - title = { - PlaceholderAtom(width = 200.dp, height = 22.dp) - }, - subtitle = { - PlaceholderAtom(width = 140.dp, height = 20.dp) - }, - ) - } + } + ) + } + is ContentState.UnknownRoom -> { + ContentScaffold( + modifier = modifier, + avatar = { + PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) + }, + title = { + Title(stringResource(R.string.screen_join_room_title_no_preview)) + }, + subtitle = { + Subtitle(stringResource(R.string.screen_join_room_subtitle_no_preview)) + }, + ) + } + is ContentState.Loading -> { + ContentScaffold( + modifier = modifier, + avatar = { + PlaceholderAtom(width = AvatarSize.RoomHeader.dp, height = AvatarSize.RoomHeader.dp) + }, + title = { + PlaceholderAtom(width = 200.dp, height = 22.dp) + }, + subtitle = { + PlaceholderAtom(width = 140.dp, height = 20.dp) + }, + ) } } } @@ -200,23 +195,29 @@ private fun ContentScaffold( avatar: @Composable () -> Unit, title: @Composable () -> Unit, subtitle: @Composable () -> Unit, + modifier: Modifier = Modifier, description: @Composable (() -> Unit)? = null, memberCount: @Composable (() -> Unit)? = null, ) { - avatar() - Spacer(modifier = Modifier.height(16.dp)) - title() - Spacer(modifier = Modifier.height(8.dp)) - subtitle() - Spacer(modifier = Modifier.height(8.dp)) - if (memberCount != null) { - memberCount() - } - Spacer(modifier = Modifier.height(8.dp)) - if (description != null) { - description() + Column( + modifier = modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + avatar() + Spacer(modifier = Modifier.height(16.dp)) + title() + Spacer(modifier = Modifier.height(8.dp)) + subtitle() + Spacer(modifier = Modifier.height(8.dp)) + if (memberCount != null) { + memberCount() + } + Spacer(modifier = Modifier.height(8.dp)) + if (description != null) { + description() + } + Spacer(modifier = Modifier.height(24.dp)) } - Spacer(modifier = Modifier.height(24.dp)) } @Composable @@ -256,12 +257,11 @@ private fun Description(description: String, modifier: Modifier = Modifier) { @Composable private fun MembersCount(memberCount: Long) { - Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier - .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) - .widthIn(min = 48.dp) - .padding(all = 2.dp), + .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) + .widthIn(min = 48.dp) + .padding(all = 2.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp) ) { 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 19cc23c995..056482cca9 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 @@ -41,7 +41,6 @@ import org.junit.Test import java.util.Optional class JoinRoomPresenterTest { - @get:Rule val warmUpRule = WarmUpRule() @@ -136,7 +135,6 @@ class JoinRoomPresenterTest { listOf(value(AcceptDeclineInviteEvents.AcceptInvite(inviteData))), listOf(value(AcceptDeclineInviteEvents.DeclineInvite(inviteData))), ) - } } } diff --git a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt index 1585151614..664ca4bd28 100644 --- a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt +++ b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt @@ -164,7 +164,7 @@ class LeaveRoomPresenterImplTest { givenGetRoomResult( roomId = A_ROOM_ID, result = FakeMatrixRoom().apply { - this.leaveRoomLambda = { Result.failure(RuntimeException("Blimey!"))} + this.leaveRoomLambda = { Result.failure(RuntimeException("Blimey!")) } }, ) } @@ -210,7 +210,7 @@ class LeaveRoomPresenterImplTest { givenGetRoomResult( roomId = A_ROOM_ID, result = FakeMatrixRoom().apply { - this.leaveRoomLambda = { Result.failure(RuntimeException("Blimey!"))} + this.leaveRoomLambda = { Result.failure(RuntimeException("Blimey!")) } }, ) } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt index 9665c886d7..6cd7cf82ce 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt @@ -18,11 +18,9 @@ package io.element.android.features.location.impl.common.actions import com.google.common.truth.Truth.assertThat import io.element.android.features.location.api.Location -import org.junit.Ignore import org.junit.Test import java.net.URLEncoder -@Ignore internal class AndroidLocationActionsTest { // We use an Android-native encoder in the actual app, switch to an equivalent JVM one for the tests private fun urlEncoder(input: String) = URLEncoder.encode(input, "US-ASCII") diff --git a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt index 632173100a..a27f413e9b 100644 --- a/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt +++ b/features/roomdirectory/api/src/main/kotlin/io/element/android/features/roomdirectory/api/RoomDescription.kt @@ -21,6 +21,7 @@ import androidx.compose.runtime.Immutable import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomId +import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @Parcelize @@ -34,15 +35,16 @@ data class RoomDescription( val joinRule: JoinRule, val numberOfMembers: Long, ) : Parcelable { - enum class JoinRule { PUBLIC, KNOCK, UNKNOWN } + @IgnoredOnParcel val computedName = name ?: alias ?: roomId.value + @IgnoredOnParcel val computedDescription: String get() { return when { @@ -53,7 +55,8 @@ data class RoomDescription( } } - fun canBeJoined() = joinRule == JoinRule.PUBLIC || joinRule == JoinRule.KNOCK + @IgnoredOnParcel + val canJoinOrKnock = joinRule == JoinRule.PUBLIC || joinRule == JoinRule.KNOCK fun avatarData(size: AvatarSize) = AvatarData( id = roomId.value, diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryNode.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryNode.kt index a9e5f2cff5..32f9571d44 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryNode.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryNode.kt @@ -36,7 +36,6 @@ class RoomDirectoryNode @AssistedInject constructor( @Assisted plugins: List, private val presenter: RoomDirectoryPresenter, ) : Node(buildContext, plugins = plugins) { - private fun onResultClicked(roomDescription: RoomDescription) { plugins().forEach { it.onResultClicked(roomDescription) diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt index c8fe34e85e..d6eeb65d7c 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt @@ -91,8 +91,8 @@ fun RoomDirectoryView( onResultClicked = onResultClicked, onJoinClicked = ::joinRoom, modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) + .padding(padding) + .consumeWindowInsets(padding) ) } ) @@ -199,10 +199,10 @@ private fun RoomDirectoryRoomList( @Composable private fun LoadMoreIndicator(modifier: Modifier = Modifier) { Box( - modifier - .fillMaxWidth() - .wrapContentHeight() - .padding(24.dp), + modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(24.dp), contentAlignment = Alignment.Center, ) { CircularProgressIndicator( @@ -273,14 +273,14 @@ private fun RoomDirectoryRoomRow( ) { Row( modifier = modifier - .fillMaxWidth() - .clickable(onClick = onClick) - .padding( - top = 12.dp, - bottom = 12.dp, - start = 16.dp, - ) - .height(IntrinsicSize.Min), + .fillMaxWidth() + .clickable(onClick = onClick) + .padding( + top = 12.dp, + bottom = 12.dp, + start = 16.dp, + ) + .height(IntrinsicSize.Min), ) { Avatar( avatarData = roomDescription.avatarData(AvatarSize.RoomDirectoryItem), @@ -288,8 +288,8 @@ private fun RoomDirectoryRoomRow( ) Column( modifier = Modifier - .weight(1f) - .padding(start = 16.dp) + .weight(1f) + .padding(start = 16.dp) ) { Text( text = roomDescription.computedName, @@ -306,15 +306,15 @@ private fun RoomDirectoryRoomRow( overflow = TextOverflow.Ellipsis, ) } - if (roomDescription.canBeJoined()) { + if (roomDescription.canJoinOrKnock) { Text( text = stringResource(id = CommonStrings.action_join), color = ElementTheme.colors.textSuccessPrimary, modifier = Modifier - .align(Alignment.CenterVertically) - .clickable(onClick = onJoinClick) - .padding(start = 4.dp, end = 12.dp) - .testTag(TestTags.callToAction.value) + .align(Alignment.CenterVertically) + .clickable(onClick = onJoinClick) + .padding(start = 4.dp, end = 12.dp) + .testTag(TestTags.callToAction.value) ) } else { Spacer(modifier = Modifier.width(24.dp)) diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt index 994f20dd16..9038a1a0d6 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/model/RoomDescription.kt @@ -20,7 +20,6 @@ import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription as MatrixRoomDescription fun MatrixRoomDescription.toFeatureModel(): RoomDescription { - return RoomDescription( roomId = roomId, name = name, diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt index 39a63d2923..ce949250f0 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt @@ -17,12 +17,9 @@ package io.element.android.features.roomdirectory.impl.root import androidx.activity.ComponentActivity -import androidx.compose.ui.res.stringResource import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onAllNodesWithTag -import androidx.compose.ui.test.onAllNodesWithText -import androidx.compose.ui.test.onChild import androidx.compose.ui.test.onFirst import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText @@ -33,7 +30,6 @@ import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.testtags.TestTags -import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EnsureNeverCalledWithParam import io.element.android.tests.testutils.EventsRecorder @@ -74,7 +70,7 @@ class RoomDirectoryViewTest { state = state, onResultClicked = callback, ) - rule.onNodeWithText(clickedRoom.name).performClick() + rule.onNodeWithText(clickedRoom.computedName).performClick() } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt index 71dfecddb8..3cae67cb1b 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt @@ -35,6 +35,7 @@ import io.element.android.libraries.designsystem.theme.components.Text /** * @param modifier Classical modifier. + * @param paddingValues padding values to apply to the content. * @param background optional background component. * @param topBar optional topBar. * @param header optional header. 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 7814c05946..24a034c070 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 @@ -27,7 +27,6 @@ import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService -import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -100,4 +99,3 @@ interface MatrixClient : Closeable { suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result suspend fun getRecentlyVisitedRooms(): Result> } - diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt index 860aeb7e68..95992b965e 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt @@ -79,11 +79,8 @@ interface RoomListService { * The state of the service as a flow. */ val state: StateFlow - } fun RoomList.loadedStateFlow(): Flow { return loadingState.filterIsInstance() } - - 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 7044f44c53..7e86f29cb7 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 @@ -276,5 +276,4 @@ class FakeMatrixClient( } override fun getRoomInfoFlow(roomId: RoomId) = getRoomInfoFlowLambda(roomId) - } diff --git a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt index fef7eb2484..3046ba3372 100644 --- a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt +++ b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt @@ -107,7 +107,7 @@ object TestTags { val searchTextField = TestTag("search_text_field") /** - * Generic call to action + * Generic call to action. */ val callToAction = TestTag("call_to_action") } From a41096fa51d8588a63467bf83b701e9c3f539ed8 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Apr 2024 16:45:40 +0200 Subject: [PATCH 21/52] Fix malformed room id in StateProvider.. --- .../invite/api/response/AcceptDeclineInviteStateProvider.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteStateProvider.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteStateProvider.kt index e6a20d9b80..af2c37e68f 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteStateProvider.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/response/AcceptDeclineInviteStateProvider.kt @@ -27,13 +27,13 @@ open class AcceptDeclineInviteStateProvider : PreviewParameterProvider Date: Fri, 12 Apr 2024 14:57:03 +0000 Subject: [PATCH 22/52] Update screenshots --- ...ull_LoadingRoomNodeView-Day-2_2_null_0,NEXUS_5,1.0,en].png} | 0 ...ull_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,en].png} | 0 ...l_LoadingRoomNodeView-Night-2_3_null_0,NEXUS_5,1.0,en].png} | 0 ...l_LoadingRoomNodeView-Night-2_3_null_1,NEXUS_5,1.0,en].png} | 0 ...w_null_InviteSummaryRow-Day-0_1_null_0,NEXUS_5,1.0,en].png} | 0 ...w_null_InviteSummaryRow-Day-0_1_null_1,NEXUS_5,1.0,en].png} | 0 ...w_null_InviteSummaryRow-Day-0_1_null_2,NEXUS_5,1.0,en].png} | 0 ...w_null_InviteSummaryRow-Day-0_1_null_3,NEXUS_5,1.0,en].png} | 0 ...w_null_InviteSummaryRow-Day-0_1_null_4,NEXUS_5,1.0,en].png} | 0 ...null_InviteSummaryRow-Night-0_2_null_0,NEXUS_5,1.0,en].png} | 0 ...null_InviteSummaryRow-Night-0_2_null_1,NEXUS_5,1.0,en].png} | 0 ...null_InviteSummaryRow-Night-0_2_null_2,NEXUS_5,1.0,en].png} | 0 ...null_InviteSummaryRow-Night-0_2_null_3,NEXUS_5,1.0,en].png} | 0 ...null_InviteSummaryRow-Night-0_2_null_4,NEXUS_5,1.0,en].png} | 0 ...iew_null_InviteListView-Day-1_2_null_0,NEXUS_5,1.0,en].png} | 0 ...iew_null_InviteListView-Day-1_2_null_1,NEXUS_5,1.0,en].png} | 0 ...View_null_InviteListView-Day-1_2_null_2,NEXUS_5,1.0,en].png | 3 +++ ...iew_null_InviteListView-Day-1_2_null_3,NEXUS_5,1.0,en].png} | 0 ...View_null_InviteListView-Day-1_2_null_4,NEXUS_5,1.0,en].png | 3 +++ ...View_null_InviteListView-Day-1_2_null_5,NEXUS_5,1.0,en].png | 3 +++ ...View_null_InviteListView-Day-1_2_null_6,NEXUS_5,1.0,en].png | 3 +++ ...w_null_InviteListView-Night-1_3_null_0,NEXUS_5,1.0,en].png} | 0 ...w_null_InviteListView-Night-1_3_null_1,NEXUS_5,1.0,en].png} | 0 ...ew_null_InviteListView-Night-1_3_null_2,NEXUS_5,1.0,en].png | 3 +++ ...w_null_InviteListView-Night-1_3_null_3,NEXUS_5,1.0,en].png} | 0 ...ew_null_InviteListView-Night-1_3_null_4,NEXUS_5,1.0,en].png | 3 +++ ...ew_null_InviteListView-Night-1_3_null_5,NEXUS_5,1.0,en].png | 3 +++ ...ew_null_InviteListView-Night-1_3_null_6,NEXUS_5,1.0,en].png | 3 +++ ...View_null_InviteListView-Day-0_1_null_3,NEXUS_5,1.0,en].png | 3 --- ...View_null_InviteListView-Day-0_1_null_4,NEXUS_5,1.0,en].png | 3 --- ...View_null_InviteListView-Day-0_1_null_5,NEXUS_5,1.0,en].png | 3 --- ...ew_null_InviteListView-Night-0_2_null_3,NEXUS_5,1.0,en].png | 3 --- ...ew_null_InviteListView-Night-0_2_null_4,NEXUS_5,1.0,en].png | 3 --- ...ew_null_InviteListView-Night-0_2_null_5,NEXUS_5,1.0,en].png | 3 --- 34 files changed, 24 insertions(+), 18 deletions(-) rename tests/uitests/src/test/snapshots/images/{ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_0,NEXUS_5,1.0,en].png => ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,en].png => ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_0,NEXUS_5,1.0,en].png => ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_1,NEXUS_5,1.0,en].png => ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_1,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_1,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_1,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_2,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_2,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_3,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_3,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_4,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_4,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_1,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_1,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_2,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_2,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_3,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_3,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_4,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_4,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_1,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_1,NEXUS_5,1.0,en].png} (100%) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_2,NEXUS_5,1.0,en].png rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_2,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_3,NEXUS_5,1.0,en].png} (100%) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_4,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_5,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_6,NEXUS_5,1.0,en].png rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_1,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_1,NEXUS_5,1.0,en].png} (100%) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_2,NEXUS_5,1.0,en].png rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_2,NEXUS_5,1.0,en].png => ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_3,NEXUS_5,1.0,en].png} (100%) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_4,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_5,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_6,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_3,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_4,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_5,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_3,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_4,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_5,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_1,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_1,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_1,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_1,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_1,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_1,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_2,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_2,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_2,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_3,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_3,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_3,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_4,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_4,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_4,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_1,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_1,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_1,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_2,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_2,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_2,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_3,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_3,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_3,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_4,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_4,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_4,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_1,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_1,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_1,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_2,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..f9e386b0a2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_2,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa90fb393dcb986721190468a83b7b9956e97e2a89d809913ea8895b0f698eba +size 54691 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_3,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_2,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_3,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_4,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..7885f98840 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_4,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb75ce275178fd84581680df4ba8cfe0cc4a5db079160a0a1c22e717521efb56 +size 54607 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_5,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..8454a07904 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_5,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3dfe58becc60142b7547331dc4c263e761930dcf0dbb11d4e1efcbfaf618cb31 +size 42625 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_6,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..8454a07904 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_6,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3dfe58becc60142b7547331dc4c263e761930dcf0dbb11d4e1efcbfaf618cb31 +size 42625 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_1,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_1,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_1,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_2,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..bc150d35ac --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_2,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb2e96e4737a2616676439c4d6ce85279c7ea9f09129058818502658841e8f10 +size 51858 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_3,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_2,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_3,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_4,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..958a3d1254 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_4,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5fd489d8088e8afd11738f52417cff00ff720ea493ac9b8d350b10c1b1effd0 +size 49458 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_5,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..a70274e954 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_5,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76f3386f41e0b2daad020c08e577e9f7266c8f80e2cb020c6f6d4f51126d182b +size 37982 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_6,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..a70274e954 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_6,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76f3386f41e0b2daad020c08e577e9f7266c8f80e2cb020c6f6d4f51126d182b +size 37982 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_3,NEXUS_5,1.0,en].png deleted file mode 100644 index 34611720e6..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_3,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fa1bed037eb1bac4ff3e5ce5bf477d646b19c40744e9529f05c331083985be4d -size 54707 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_4,NEXUS_5,1.0,en].png deleted file mode 100644 index 506f9344a5..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_4,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c42f6c5a1378d921530457716c59dc0b8685d0ce974224a3805f31d2c83a5f58 -size 44419 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_5,NEXUS_5,1.0,en].png deleted file mode 100644 index 506f9344a5..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_5,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c42f6c5a1378d921530457716c59dc0b8685d0ce974224a3805f31d2c83a5f58 -size 44419 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_3,NEXUS_5,1.0,en].png deleted file mode 100644 index 89d6f7b185..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_3,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:323e331e3be97ce4c20b21d4f72ed4d9528b2b3520201289b5fff4c8c2a95a6e -size 49637 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_4,NEXUS_5,1.0,en].png deleted file mode 100644 index fdb5d56575..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_4,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b7cdaa24081b0169e704e9e7084cdc263da54e79429dcfde87ea9a324fa1607c -size 39715 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_5,NEXUS_5,1.0,en].png deleted file mode 100644 index fdb5d56575..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_5,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b7cdaa24081b0169e704e9e7084cdc263da54e79429dcfde87ea9a324fa1607c -size 39715 From efde2af29eb6118fa783c1e187163c1c89684a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 12 Apr 2024 16:05:38 +0200 Subject: [PATCH 23/52] Compound: add `SuperButton` and `GradientFloatingActionButton` components Also add `ButtonSize.Small` and adjust existing `Button` component --- .../button/GradientFloatingActionButton.kt | 149 +++++++++++++ .../components/button/SuperButton.kt | 196 ++++++++++++++++++ .../designsystem/theme/components/Button.kt | 38 +++- 3 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/GradientFloatingActionButton.kt create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/GradientFloatingActionButton.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/GradientFloatingActionButton.kt new file mode 100644 index 0000000000..d600f92326 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/GradientFloatingActionButton.kt @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.components.button + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.minimumInteractiveComponentSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.geometry.center +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.LinearGradientShader +import androidx.compose.ui.graphics.RadialGradientShader +import androidx.compose.ui.graphics.Shader +import androidx.compose.ui.graphics.ShaderBrush +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.unit.dp +import io.element.android.compound.annotations.CoreColorToken +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.compound.tokens.generated.internal.LightColorTokens +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Icon + +@OptIn(CoreColorToken::class) +@Composable +fun GradientFloatingActionButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + shape: Shape = RoundedCornerShape(25), + content: @Composable () -> Unit, +) { + Box { + val linearShaderBrush = remember { + object : ShaderBrush() { + override fun createShader(size: Size): Shader { + return LinearGradientShader( + from = Offset(size.width, size.height), + to = Offset(size.width, 0f), + colors = listOf( + LightColorTokens.colorBlue900, + LightColorTokens.colorGreen700, + ), + ) + } + } + } + val radialShaderBrush = remember { + object : ShaderBrush() { + override fun createShader(size: Size): Shader { + return RadialGradientShader( + center = size.center, + radius = size.width / 2, + colors = listOf( + LightColorTokens.colorGreen700, + LightColorTokens.colorBlue900, + ) + ) + } + } + } + + Box( + modifier = modifier + .minimumInteractiveComponentSize() + .graphicsLayer(shape = shape, clip = false) + .clip(shape) + .drawBehind { + drawRect(brush = radialShaderBrush, alpha = 0.4f) + drawRect(brush = linearShaderBrush) + } + .clickable( + enabled = true, + onClick = onClick, + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(color = Color.White) + ), + contentAlignment = Alignment.Center + ) { + CompositionLocalProvider(LocalContentColor provides Color.White) { + content() + } + } + } +} + +@PreviewsDayNight +@Composable +internal fun GradientFloatingActionButtonPreview() { + ElementPreview { + Box(modifier = Modifier.padding(20.dp)) { + GradientFloatingActionButton( + modifier = Modifier.size(48.dp), + onClick = {}, + ) { + Icon(imageVector = CompoundIcons.ChatNew(), contentDescription = null) + } + } + } +} + +@PreviewsDayNight +@Composable +internal fun GradientSendButtonPreview() { + ElementPreview { + Box(modifier = Modifier.padding(20.dp)) { + GradientFloatingActionButton( + shape = CircleShape, + modifier = Modifier.size(48.dp), + onClick = {}, + ) { + Icon( + modifier = Modifier.padding(start = 2.dp), + imageVector = CompoundIcons.SendSolid(), + contentDescription = null + ) + } + } + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt new file mode 100644 index 0000000000..dbd03091ed --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.components.button + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.Text +import androidx.compose.material3.minimumInteractiveComponentSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.LinearGradientShader +import androidx.compose.ui.graphics.Shader +import androidx.compose.ui.graphics.ShaderBrush +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.unit.dp +import io.element.android.compound.annotations.CoreColorToken +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.internal.DarkColorTokens +import io.element.android.compound.tokens.generated.internal.LightColorTokens +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.ButtonSize +import io.element.android.libraries.designsystem.theme.components.HorizontalDivider + +@OptIn(CoreColorToken::class) +@Composable +fun SuperButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + shape: Shape = RoundedCornerShape(50), + buttonSize: ButtonSize = ButtonSize.Large, + enabled: Boolean = true, + content: @Composable () -> Unit, +) { + val contentPadding = remember(buttonSize) { + when (buttonSize) { + ButtonSize.Large -> PaddingValues(horizontal = 24.dp, vertical = 13.dp) + ButtonSize.Medium -> PaddingValues(horizontal = 20.dp, vertical = 9.dp) + ButtonSize.Small -> PaddingValues(horizontal = 16.dp, vertical = 5.dp) + } + } + Box { + val isLightTheme = ElementTheme.isLightTheme + val colors = remember(isLightTheme) { + if (isLightTheme) { + listOf( + LightColorTokens.colorBlue900, + LightColorTokens.colorGreen1100, + ) + } else { + listOf( + DarkColorTokens.colorBlue900, + DarkColorTokens.colorGreen1100, + ) + } + } + + val shaderBrush = remember(colors) { + object : ShaderBrush() { + override fun createShader(size: Size): Shader { + return LinearGradientShader( + from = Offset(0f, size.height), + to = Offset(size.width, 0f), + colors = colors, + ) + } + } + } + val border = if (enabled) { + BorderStroke(1.dp, shaderBrush) + } else { + BorderStroke(1.dp, ElementTheme.colors.borderDisabled) + } + val backgroundColor = ElementTheme.colors.bgCanvasDefault + Box( + modifier = modifier + .minimumInteractiveComponentSize() + .graphicsLayer(shape = shape, clip = false) + .clip(shape) + .border(border, shape) + .drawBehind { + drawRect(backgroundColor) + drawRect(brush = shaderBrush, alpha = 0.04f) + } + .clickable( + enabled = enabled, + onClick = onClick, + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple() + ) + .padding(contentPadding), + contentAlignment = Alignment.Center + ) { + CompositionLocalProvider( + LocalContentColor provides if (enabled) ElementTheme.colors.textPrimary else ElementTheme.colors.textDisabled, + LocalTextStyle provides ElementTheme.typography.fontBodyLgMedium, + ) { + content() + } + } + } +} + +@PreviewsDayNight +@Composable +internal fun SuperButtonPreview() { + ElementPreview { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + SuperButton( + modifier = Modifier.padding(10.dp), + buttonSize = ButtonSize.Large, + onClick = {}, + ) { + Text("Super button!") + } + + SuperButton( + modifier = Modifier.padding(10.dp), + buttonSize = ButtonSize.Medium, + onClick = {}, + ) { + Text("Super button!") + } + + SuperButton( + modifier = Modifier.padding(10.dp), + buttonSize = ButtonSize.Small, + onClick = {}, + ) { + Text("Super button!") + } + + HorizontalDivider() + + SuperButton( + modifier = Modifier.padding(10.dp), + buttonSize = ButtonSize.Large, + enabled = false, + onClick = {}, + ) { + Text("Super button!") + } + + SuperButton( + modifier = Modifier.padding(10.dp), + buttonSize = ButtonSize.Medium, + enabled = false, + onClick = {}, + ) { + Text("Super button!") + } + + SuperButton( + modifier = Modifier.padding(10.dp), + buttonSize = ButtonSize.Small, + enabled = false, + onClick = {}, + ) { + Text("Super button!") + } + } + } +} + diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt index 6470cd0c8b..b832c49587 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt @@ -138,6 +138,7 @@ private fun ButtonInternal( leadingIcon: IconSource? = null, ) { val minHeight = when (size) { + ButtonSize.Small -> 32.dp ButtonSize.Medium -> 40.dp ButtonSize.Large -> 48.dp } @@ -145,6 +146,13 @@ private fun ButtonInternal( val hasStartDrawable = showProgress || leadingIcon != null val contentPadding = when (size) { + ButtonSize.Small -> { + if (hasStartDrawable) { + PaddingValues(start = 8.dp, top = 5.dp, end = 16.dp, bottom = 5.dp) + } else { + PaddingValues(start = 16.dp, top = 5.dp, end = 16.dp, bottom = 5.dp) + } + } ButtonSize.Medium -> when (style) { ButtonStyle.Filled, ButtonStyle.Outlined -> if (hasStartDrawable) { @@ -195,7 +203,7 @@ private fun ButtonInternal( } val textStyle = when (size) { - ButtonSize.Medium -> MaterialTheme.typography.labelLarge + ButtonSize.Small, ButtonSize.Medium -> MaterialTheme.typography.labelLarge ButtonSize.Large -> ElementTheme.typography.fontBodyLgMedium } @@ -259,6 +267,7 @@ sealed interface IconSource { } enum class ButtonSize { + Small, Medium, Large } @@ -317,6 +326,15 @@ internal enum class ButtonStyle { } } +@Preview(group = PreviewGroup.Buttons) +@Composable +internal fun FilledButtonSmallPreview() { + ButtonCombinationPreview( + style = ButtonStyle.Filled, + size = ButtonSize.Small, + ) +} + @Preview(group = PreviewGroup.Buttons) @Composable internal fun FilledButtonMediumPreview() { @@ -335,6 +353,15 @@ internal fun FilledButtonLargePreview() { ) } +@Preview(group = PreviewGroup.Buttons) +@Composable +internal fun OutlinedButtonSmallPreview() { + ButtonCombinationPreview( + style = ButtonStyle.Outlined, + size = ButtonSize.Small, + ) +} + @Preview(group = PreviewGroup.Buttons) @Composable internal fun OutlinedButtonMediumPreview() { @@ -353,6 +380,15 @@ internal fun OutlinedButtonLargePreview() { ) } +@Preview(group = PreviewGroup.Buttons) +@Composable +internal fun TextButtonSmallPreview() { + ButtonCombinationPreview( + style = ButtonStyle.Text, + size = ButtonSize.Small, + ) +} + @Preview(group = PreviewGroup.Buttons) @Composable internal fun TextButtonMediumPreview() { From 9b73dcd868ab3f424aed9891f5936c6e31fc3356 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 12 Apr 2024 15:10:13 +0000 Subject: [PATCH 24/52] Update screenshots --- ...GradientFloatingActionButton-Day_0_null,NEXUS_5,1.0,en].png | 3 +++ ...adientFloatingActionButton-Night_1_null,NEXUS_5,1.0,en].png | 3 +++ ...tton_null_GradientSendButton-Day_0_null,NEXUS_5,1.0,en].png | 3 +++ ...on_null_GradientSendButton-Night_1_null,NEXUS_5,1.0,en].png | 3 +++ ...SuperButton_null_SuperButton-Day_0_null,NEXUS_5,1.0,en].png | 3 +++ ...perButton_null_SuperButton-Night_1_null,NEXUS_5,1.0,en].png | 3 +++ ...l_null_Buttons_FilledButtonSmall_0_null,NEXUS_5,1.0,en].png | 3 +++ ...null_Buttons_OutlinedButtonSmall_0_null,NEXUS_5,1.0,en].png | 3 +++ ...all_null_Buttons_TextButtonSmall_0_null,NEXUS_5,1.0,en].png | 3 +++ 9 files changed, 27 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientFloatingActionButton_null_GradientFloatingActionButton-Day_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientFloatingActionButton_null_GradientFloatingActionButton-Night_1_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientSendButton_null_GradientSendButton-Day_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientSendButton_null_GradientSendButton-Night_1_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_SuperButton_null_SuperButton-Day_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_SuperButton_null_SuperButton-Night_1_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_FilledButtonSmall_null_Buttons_FilledButtonSmall_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_OutlinedButtonSmall_null_Buttons_OutlinedButtonSmall_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_TextButtonSmall_null_Buttons_TextButtonSmall_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientFloatingActionButton_null_GradientFloatingActionButton-Day_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientFloatingActionButton_null_GradientFloatingActionButton-Day_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..107d64cabd --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientFloatingActionButton_null_GradientFloatingActionButton-Day_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cae4b9086f68755b300d2200d49755183df5e9e1e23cdab937aede8e4a473e18 +size 7886 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientFloatingActionButton_null_GradientFloatingActionButton-Night_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientFloatingActionButton_null_GradientFloatingActionButton-Night_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..0d901392da --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientFloatingActionButton_null_GradientFloatingActionButton-Night_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3d11615261dcbefa4fd78cfc111c601a87c80060d19a5881ede28ee531b1dd4 +size 7815 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientSendButton_null_GradientSendButton-Day_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientSendButton_null_GradientSendButton-Day_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..27defedd12 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientSendButton_null_GradientSendButton-Day_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f59b4185d583aa3e42ab1449cb4dc9c46314cd4e00e8c7f8ea0e6db5a8560556 +size 8393 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientSendButton_null_GradientSendButton-Night_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientSendButton_null_GradientSendButton-Night_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..e015eab091 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_GradientSendButton_null_GradientSendButton-Night_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c298a041d27639e42bc3e65d99d2c0865d499faf0f195f468ec32e1c372691a8 +size 8275 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_SuperButton_null_SuperButton-Day_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_SuperButton_null_SuperButton-Day_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..efd2eb0c96 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_SuperButton_null_SuperButton-Day_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46bd7f805daa3ba70cecf8f75439415d0c37a9387118277ba034e5b14e2c08ed +size 57840 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_SuperButton_null_SuperButton-Night_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_SuperButton_null_SuperButton-Night_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..7b0bf20187 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.button_SuperButton_null_SuperButton-Night_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:989ee65e0c17961e226f5307f248b607b8741246d17d036bf7a6d345f8f3c93d +size 58331 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_FilledButtonSmall_null_Buttons_FilledButtonSmall_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_FilledButtonSmall_null_Buttons_FilledButtonSmall_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..3cfdde8536 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_FilledButtonSmall_null_Buttons_FilledButtonSmall_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fcab510e8f74975d5d4fccb627983752d607c768805e6a69ba5c606f78ec66c5 +size 62261 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_OutlinedButtonSmall_null_Buttons_OutlinedButtonSmall_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_OutlinedButtonSmall_null_Buttons_OutlinedButtonSmall_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..ed7700c98d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_OutlinedButtonSmall_null_Buttons_OutlinedButtonSmall_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9aae210997acac9c248f01ad7879f00b9f94f4ba86bf91cf81f98c8c32c94d0 +size 70241 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_TextButtonSmall_null_Buttons_TextButtonSmall_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_TextButtonSmall_null_Buttons_TextButtonSmall_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..dae2dc2f3b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_TextButtonSmall_null_Buttons_TextButtonSmall_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c1c1771b5d23e02261fdd38cb0995ef29b8d3d77f227da6bca35dff64c62256 +size 45971 From 84a4676277df44df33d611356d98f47fdb0d803c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 15:44:39 +0000 Subject: [PATCH 25/52] Update dependency org.matrix.rustcomponents:sdk-android to v0.2.14 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a3f56eaaf8..6b6e38ad6b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -154,7 +154,7 @@ jsoup = "org.jsoup:jsoup:1.17.2" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:1.4.2" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.13" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.14" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From 794e3440fdb61260a75a74d9747306aadee3a2bd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Apr 2024 18:16:17 +0200 Subject: [PATCH 26/52] Use `ContentState.Loading` instead of `ContentState.UnknownRoom`. --- .../element/android/features/joinroom/impl/JoinRoomPresenter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6bcb09b4c9..5b3225575f 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 @@ -56,7 +56,7 @@ class JoinRoomPresenter @AssistedInject constructor( roomDescription.get().toContentState() } else -> { - ContentState.UnknownRoom(roomId) + ContentState.Loading(roomId) } } } From 64c66b44545ca2ea58ba1bde510eba617bdcd34b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Apr 2024 18:45:34 +0200 Subject: [PATCH 27/52] Fix preview of JoinRoomView --- .../features/joinroom/impl/JoinRoomStateProvider.kt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 0982980204..82b81d8e7b 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -25,7 +25,7 @@ open class JoinRoomStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aJoinRoomState( - contentState = anUninitializedContentState() + contentState = aLoadingContentState() ), aJoinRoomState( contentState = anUnknownContentState() @@ -42,13 +42,13 @@ open class JoinRoomStateProvider : PreviewParameterProvider { ) } -fun anUnknownContentState(roomId: RoomId = RoomId("@exa:matrix.org")) = ContentState.UnknownRoom(roomId) +fun anUnknownContentState(roomId: RoomId = A_ROOM_ID) = ContentState.UnknownRoom(roomId) -fun anUninitializedContentState(roomId: RoomId = RoomId("@exa:matrix.org")) = ContentState.Loading(roomId) +fun aLoadingContentState(roomId: RoomId = A_ROOM_ID) = ContentState.Loading(roomId) fun aLoadedContentState( - roomId: RoomId = RoomId("@exa:matrix.org"), - name: String = "Element x android", + roomId: RoomId = A_ROOM_ID, + name: String = "Element X android", alias: String? = "#exa:matrix.org", topic: String? = "Element X is a secure, private and decentralized messenger.", numberOfMembers: Long? = null, @@ -75,3 +75,5 @@ fun aJoinRoomState( acceptDeclineInviteState = acceptDeclineInviteState, eventSink = eventSink ) + +private val A_ROOM_ID = RoomId("!exa:matrix.org") From 61f76533b97a1caa54358d1dfd1cc426a74926d7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Apr 2024 18:45:43 +0200 Subject: [PATCH 28/52] Format --- .../element/android/features/joinroom/impl/JoinRoomView.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 3176924c9a..31f065c0e5 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -259,9 +259,9 @@ private fun Description(description: String, modifier: Modifier = Modifier) { private fun MembersCount(memberCount: Long) { Row( modifier = Modifier - .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) - .widthIn(min = 48.dp) - .padding(all = 2.dp), + .background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape) + .widthIn(min = 48.dp) + .padding(all = 2.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp) ) { From 6e2d163dcf7cf135183b673cbd82f1d6ceaa6062 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Thu, 11 Apr 2024 18:13:19 +0200 Subject: [PATCH 29/52] Fix compile with noop analytics provider --- changelog.d/2698.misc | 1 + services/analytics/noop/build.gradle.kts | 2 +- .../analytics/noop/NoopScreenTracker.kt | 30 +++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 changelog.d/2698.misc create mode 100644 services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopScreenTracker.kt diff --git a/changelog.d/2698.misc b/changelog.d/2698.misc new file mode 100644 index 0000000000..a15fdd9f7a --- /dev/null +++ b/changelog.d/2698.misc @@ -0,0 +1 @@ +Fix compile for forks that use the `noop` analytics module diff --git a/services/analytics/noop/build.gradle.kts b/services/analytics/noop/build.gradle.kts index 000434a05c..e19ca914ce 100644 --- a/services/analytics/noop/build.gradle.kts +++ b/services/analytics/noop/build.gradle.kts @@ -14,7 +14,7 @@ * limitations under the License. */ plugins { - id("io.element.android-library") + id("io.element.android-compose-library") alias(libs.plugins.anvil) } diff --git a/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopScreenTracker.kt b/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopScreenTracker.kt new file mode 100644 index 0000000000..20f8f5dd60 --- /dev/null +++ b/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopScreenTracker.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analytics.noop + +import androidx.compose.runtime.Composable +import com.squareup.anvil.annotations.ContributesBinding +import im.vector.app.features.analytics.plan.MobileScreen +import io.element.android.libraries.di.AppScope +import io.element.android.services.analytics.api.ScreenTracker +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class NoopScreenTracker @Inject constructor() : ScreenTracker { + @Composable + override fun TrackScreen(screen: MobileScreen.ScreenName) = Unit +} From 4272181cc5582b7195fe0c412b412e7f1abe6c0e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 21:32:02 +0000 Subject: [PATCH 30/52] Update gradle/wrapper-validation-action action to v3 --- .github/workflows/gradle-wrapper-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index f2ad3eeee4..3c619328ae 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -12,4 +12,4 @@ jobs: # No concurrency required, this is a prerequisite to other actions and should run every time. steps: - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v2 + - uses: gradle/wrapper-validation-action@v3 From 6e7b3d301aff57bd5c160795f1a99ad388c5e2b7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 14 Apr 2024 19:31:03 +0000 Subject: [PATCH 31/52] Update telephoto to v0.10.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6b6e38ad6b..107ce8a3da 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ showkase = "1.0.2" appyx = "1.4.0" sqldelight = "2.0.2" wysiwyg = "2.37.0" -telephoto = "0.9.0" +telephoto = "0.10.0" # DI dagger = "2.51.1" From 1eb1efed52b6d89066747f6956aa042703d967d2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 08:58:06 +0200 Subject: [PATCH 32/52] Cleanup --- features/joinroom/impl/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/features/joinroom/impl/build.gradle.kts b/features/joinroom/impl/build.gradle.kts index b87410ec87..188feb662b 100644 --- a/features/joinroom/impl/build.gradle.kts +++ b/features/joinroom/impl/build.gradle.kts @@ -14,7 +14,6 @@ * limitations under the License. */ -@Suppress("DSL_SCOPE_VIOLATION") plugins { id("io.element.android-compose-library") alias(libs.plugins.anvil) From 7c5a89d77537dcca90a014dba942350e5ae07531 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 09:01:03 +0200 Subject: [PATCH 33/52] Fix test: ContentState.UnknownRoom case will be handled later. --- .../android/features/joinroom/impl/JoinRoomPresenterTest.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt index 056482cca9..e61dd18aad 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 @@ -53,9 +53,6 @@ class JoinRoomPresenterTest { assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown) assertThat(state.acceptDeclineInviteState).isEqualTo(anAcceptDeclineInviteState()) } - awaitItem().also { state -> - assertThat(state.contentState).isEqualTo(ContentState.UnknownRoom(A_ROOM_ID)) - } } } From 9e14db2739bc5c7310a11832165cd9329597853c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 10:44:45 +0200 Subject: [PATCH 34/52] Attempt to fix preview of JoinRoomView --- features/joinroom/impl/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/features/joinroom/impl/build.gradle.kts b/features/joinroom/impl/build.gradle.kts index 188feb662b..cfdddcfee8 100644 --- a/features/joinroom/impl/build.gradle.kts +++ b/features/joinroom/impl/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { api(projects.features.joinroom.api) implementation(projects.libraries.core) implementation(projects.libraries.architecture) + implementation(projects.libraries.androidutils) implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) From a5240e3294d273a9a61e1fbf39441e5613d9af10 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 10:47:28 +0200 Subject: [PATCH 35/52] Attempt to fix preview of RoomDirectoryView --- features/roomdirectory/impl/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/features/roomdirectory/impl/build.gradle.kts b/features/roomdirectory/impl/build.gradle.kts index 85bb195da3..49638ece40 100644 --- a/features/roomdirectory/impl/build.gradle.kts +++ b/features/roomdirectory/impl/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) + implementation(projects.libraries.androidutils) implementation(projects.libraries.designsystem) implementation(projects.libraries.uiStrings) implementation(projects.libraries.testtags) From 3e52a4f3bdd1e87dcbd120a6a9292ba2bb2a6093 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 11:02:16 +0200 Subject: [PATCH 36/52] Encrypt new session data with a passphrase #2703 --- changelog.d/2703.misc | 1 + .../impl/auth/RustMatrixAuthenticationService.kt | 10 ---------- .../io/element/android/samples/minimal/MainActivity.kt | 1 - 3 files changed, 1 insertion(+), 11 deletions(-) create mode 100644 changelog.d/2703.misc diff --git a/changelog.d/2703.misc b/changelog.d/2703.misc new file mode 100644 index 0000000000..06d354f25e --- /dev/null +++ b/changelog.d/2703.misc @@ -0,0 +1 @@ +Encrypt new session data with a passphrase 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 ad34e30d18..0ac0ce94f3 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 @@ -19,8 +19,6 @@ package io.element.android.libraries.matrix.impl.auth import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.extensions.mapFailure -import io.element.android.libraries.core.meta.BuildMeta -import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.SingleIn import io.element.android.libraries.matrix.api.MatrixClient @@ -60,7 +58,6 @@ class RustMatrixAuthenticationService @Inject constructor( private val passphraseGenerator: PassphraseGenerator, userCertificatesProvider: UserCertificatesProvider, proxyProvider: ProxyProvider, - private val buildMeta: BuildMeta, ) : MatrixAuthenticationService { // Passphrase which will be used for new sessions. Existing sessions will use the passphrase // stored in the SessionData. @@ -110,13 +107,6 @@ class RustMatrixAuthenticationService @Inject constructor( } private fun getDatabasePassphrase(): String? { - // TODO Remove this if block at some point - // Return a passphrase only for debug and nightly build for now - if (buildMeta.buildType == BuildType.RELEASE) { - Timber.w("New sessions will not be encrypted with a passphrase (release build)") - return null - } - val passphrase = passphraseGenerator.generatePassphrase() if (passphrase != null) { Timber.w("New sessions will be encrypted with a passphrase") diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt index 687a4e1c50..6945e5084f 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt @@ -64,7 +64,6 @@ class MainActivity : ComponentActivity() { utdTracker = UtdTracker(NoopAnalyticsService()), ), passphraseGenerator = NullPassphraseGenerator(), - buildMeta = Singleton.buildMeta, userCertificatesProvider = userCertificatesProvider, proxyProvider = proxyProvider, ) From b3ba0db887c286eb6a7927c5ce104bd0038dfe49 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 11:29:47 +0200 Subject: [PATCH 37/52] Gh Page: ensure that a row always have the same amount of cells. --- screenshots/html/script.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/screenshots/html/script.js b/screenshots/html/script.js index 5e4fb18133..48ee6746e2 100644 --- a/screenshots/html/script.js +++ b/screenshots/html/script.js @@ -191,6 +191,13 @@ function createMissingImageElement() { return text; } +function createUpToDateImageElement() { + const text = document.createElement('p'); + text.className = "missing"; + text.textContent = 'Image not updated'; + return text; +} + function convertToHumanReadableDate(modifiedDayTime) { var date = new Date(modifiedDayTime * 86400000); return date.toLocaleDateString(); @@ -270,6 +277,8 @@ function addTable() { const foreignFile = englishFile.replace("en]", `${dataLanguages[languageIndex]}]`).replace("_S_", "_T_") const fullForeignFile = `${dataLanguages[languageIndex]}/${foreignFile}.png`; td.appendChild(createImageElement(fullForeignFile, modifiedDayTime)); + } else { + td.appendChild(createUpToDateImageElement()); } } tr.appendChild(td); From d19078d3df6ca8eadf92575d9b6b3bad5c2f923d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 11:31:41 +0200 Subject: [PATCH 38/52] Hide the data picker form, let first check how it behaves in prod using the URL parameter only. I believe this will not work in prod since the file are copied after the data.js is generated. --- screenshots/html/script.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/screenshots/html/script.js b/screenshots/html/script.js index 48ee6746e2..d6b7690532 100644 --- a/screenshots/html/script.js +++ b/screenshots/html/script.js @@ -149,6 +149,7 @@ function addForm() { }; label2.appendChild(input2); form.appendChild(label2); + /* // Add a date picker to input the minimum date of modification const label3 = document.createElement('label'); label3.textContent = 'If modified since:'; @@ -168,6 +169,7 @@ function addForm() { addTable(); }; form.appendChild(dateInput); + */ // Add a span with id result to display the number of lines const lines = document.createElement('span'); lines.id = 'lines'; From 5150c77c7cd8d4106d5a03dcefa5dabb575dc9ea Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 11:38:00 +0200 Subject: [PATCH 39/52] Use today's date for new files. --- tools/test/generateAllScreenshots.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/test/generateAllScreenshots.py b/tools/test/generateAllScreenshots.py index e92f69b0fd..0018833c1c 100755 --- a/tools/test/generateAllScreenshots.py +++ b/tools/test/generateAllScreenshots.py @@ -18,6 +18,7 @@ import os import re import sys +import time from util import compare @@ -134,6 +135,9 @@ def generateJavascriptFile(): if os.path.exists(translatedFile): # Get the last modified date of the file in seconds and round to days date = os.popen("git log -1 --format=%ct -- \"" + translatedFile + "\"").read().strip() + # if date is empty, use today's date + if date == "": + date = time.time() dateDay = int(date) // 86400 dataForFile.append(dateDay) else: From 8f6a1b410ee55ade8a0a7c80d91623e4e9b58cc7 Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 15 Apr 2024 11:40:19 +0000 Subject: [PATCH 40/52] Sync Strings from Localazy --- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-be/translations.xml | 16 + .../src/main/res/values-bg/translations.xml | 1 + .../src/main/res/values-cs/translations.xml | 28 + .../src/main/res/values-de/translations.xml | 16 + .../src/main/res/values-es/translations.xml | 1 + .../src/main/res/values-fr/translations.xml | 2 +- .../src/main/res/values-hu/translations.xml | 23 + .../src/main/res/values-in/translations.xml | 5 + .../src/main/res/values-it/translations.xml | 1 + .../src/main/res/values-ro/translations.xml | 1 + .../src/main/res/values-ru/translations.xml | 16 + .../src/main/res/values-sk/translations.xml | 21 + .../src/main/res/values-uk/translations.xml | 1 + .../main/res/values-zh-rTW/translations.xml | 1 + .../impl/src/main/res/values/localazy.xml | 18 +- .../src/main/res/values-be/translations.xml | 9 + .../src/main/res/values-cs/translations.xml | 9 + .../src/main/res/values-de/translations.xml | 9 + .../src/main/res/values-fr/translations.xml | 9 + .../src/main/res/values-hu/translations.xml | 9 + .../src/main/res/values-ru/translations.xml | 9 + .../src/main/res/values-sk/translations.xml | 9 + .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-be/translations.xml | 6 +- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-hu/translations.xml | 2 +- .../src/main/res/values-be/translations.xml | 9 +- .../src/main/res/values-cs/translations.xml | 1 + .../src/main/res/values-de/translations.xml | 7 +- .../src/main/res/values-fr/translations.xml | 7 +- .../src/main/res/values-hu/translations.xml | 1 + .../src/main/res/values-in/translations.xml | 6 - .../src/main/res/values-ru/translations.xml | 5 +- .../src/main/res/values-sk/translations.xml | 7 +- .../src/main/res/values/localazy.xml | 7 +- ...deView-Day-2_2_null_1,NEXUS_5,1.0,de].png} | 0 ...tInView-Day-0_1_null_0,NEXUS_5,1.0,de].png | 4 +- ...pleView-Day-0_1_null_3,NEXUS_5,1.0,de].png | 3 + ...istView-Day-2_3_null_9,NEXUS_5,1.0,de].png | 3 + ...ootView-Day-4_5_null_3,NEXUS_5,1.0,de].png | 3 + ...tInView-Day-0_1_null_0,NEXUS_5,1.0,de].png | 4 +- ...lcomeView-Day-1_2_null,NEXUS_5,1.0,de].png | 4 +- ...aryRow-Day-0_1_null_0,NEXUS_5,1.0,de].png} | 0 ...aryRow-Day-0_1_null_1,NEXUS_5,1.0,de].png} | 0 ...aryRow-Day-0_1_null_2,NEXUS_5,1.0,de].png} | 0 ...aryRow-Day-0_1_null_3,NEXUS_5,1.0,de].png} | 0 ...aryRow-Day-0_1_null_4,NEXUS_5,1.0,de].png} | 0 ...stView-Day-1_2_null_0,NEXUS_5,1.0,de].png} | 0 ...stView-Day-1_2_null_1,NEXUS_5,1.0,de].png} | 0 ...istView-Day-1_2_null_2,NEXUS_5,1.0,de].png | 3 + ...stView-Day-1_2_null_3,NEXUS_5,1.0,de].png} | 0 ...istView-Day-1_2_null_4,NEXUS_5,1.0,de].png | 3 + ...istView-Day-1_2_null_5,NEXUS_5,1.0,de].png | 3 + ...istView-Day-1_2_null_6,NEXUS_5,1.0,de].png | 3 + ...istView-Day-0_1_null_3,NEXUS_5,1.0,de].png | 3 - ...istView-Day-0_1_null_4,NEXUS_5,1.0,de].png | 3 - ...istView-Day-0_1_null_5,NEXUS_5,1.0,de].png | 3 - ...PinView-Day-3_4_null_0,NEXUS_5,1.0,de].png | 4 +- ...PinView-Day-3_4_null_1,NEXUS_5,1.0,de].png | 4 +- ...PinView-Day-3_4_null_2,NEXUS_5,1.0,de].png | 4 +- ...PinView-Day-3_4_null_3,NEXUS_5,1.0,de].png | 4 +- ...PinView-Day-3_4_null_4,NEXUS_5,1.0,de].png | 4 +- ...esView-Day-9_10_null_0,NEXUS_5,1.0,de].png | 4 +- ...esView-Day-9_10_null_1,NEXUS_5,1.0,de].png | 4 +- ...sView-Day-9_10_null_10,NEXUS_5,1.0,de].png | 4 +- ...esView-Day-9_10_null_2,NEXUS_5,1.0,de].png | 4 +- ...esView-Day-9_10_null_3,NEXUS_5,1.0,de].png | 4 +- ...esView-Day-9_10_null_4,NEXUS_5,1.0,de].png | 4 +- ...esView-Day-9_10_null_5,NEXUS_5,1.0,de].png | 4 +- ...esView-Day-9_10_null_6,NEXUS_5,1.0,de].png | 4 +- ...esView-Day-9_10_null_7,NEXUS_5,1.0,de].png | 4 +- ...esView-Day-9_10_null_8,NEXUS_5,1.0,de].png | 4 +- ...esView-Day-9_10_null_9,NEXUS_5,1.0,de].png | 4 +- ...ongName-Day-10_11_null,NEXUS_5,1.0,de].png | 3 + ...View-Day-11_12_null_0,NEXUS_5,1.0,de].png} | 0 ...View-Day-11_12_null_1,NEXUS_5,1.0,de].png} | 0 ...View-Day-11_12_null_2,NEXUS_5,1.0,de].png} | 0 ...View-Day-11_12_null_3,NEXUS_5,1.0,de].png} | 0 ...View-Day-11_12_null_4,NEXUS_5,1.0,de].png} | 0 ...View-Day-11_12_null_5,NEXUS_5,1.0,de].png} | 0 ...View-Day-11_12_null_6,NEXUS_5,1.0,de].png} | 0 ...ryKeyView-Day-0_1_null,NEXUS_5,1.0,de].png | 3 + ...leView-Day-1_2_null_0,NEXUS_5,1.0,de].png} | 0 ...leView-Day-1_2_null_1,NEXUS_5,1.0,de].png} | 0 ...leView-Day-1_2_null_2,NEXUS_5,1.0,de].png} | 0 ...leView-Day-1_2_null_3,NEXUS_5,1.0,de].png} | 0 ...leView-Day-2_3_null_0,NEXUS_5,1.0,de].png} | 0 ...leView-Day-2_3_null_1,NEXUS_5,1.0,de].png} | 0 ...leView-Day-2_3_null_2,NEXUS_5,1.0,de].png} | 0 ...KeyView-Day-2_3_null_0,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-2_3_null_1,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-2_3_null_2,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-2_3_null_3,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-3_4_null_0,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-3_4_null_1,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-3_4_null_2,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-3_4_null_3,NEXUS_5,1.0,de].png | 3 + ...otView-Day-4_5_null_0,NEXUS_5,1.0,de].png} | 0 ...otView-Day-4_5_null_1,NEXUS_5,1.0,de].png} | 0 ...otView-Day-4_5_null_2,NEXUS_5,1.0,de].png} | 0 ...otView-Day-4_5_null_3,NEXUS_5,1.0,de].png} | 0 ...otView-Day-4_5_null_4,NEXUS_5,1.0,de].png} | 0 ...otView-Day-4_5_null_5,NEXUS_5,1.0,de].png} | 0 ...otView-Day-4_5_null_6,NEXUS_5,1.0,de].png} | 0 ...otView-Day-4_5_null_7,NEXUS_5,1.0,de].png} | 0 ...otView-Day-4_5_null_8,NEXUS_5,1.0,de].png} | 0 ...KeyView-Day-6_7_null_0,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-6_7_null_1,NEXUS_5,1.0,de].png | 3 - ...eyView-Day-6_7_null_10,NEXUS_5,1.0,de].png | 3 - ...eyView-Day-6_7_null_11,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-6_7_null_2,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-6_7_null_3,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-6_7_null_4,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-6_7_null_5,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-6_7_null_6,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-6_7_null_7,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-6_7_null_8,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-6_7_null_9,NEXUS_5,1.0,de].png | 3 - ...KeyView-Day-7_8_null_0,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-7_8_null_1,NEXUS_5,1.0,de].png | 3 + ...eyView-Day-7_8_null_10,NEXUS_5,1.0,de].png | 3 + ...eyView-Day-7_8_null_11,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-7_8_null_2,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-7_8_null_3,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-7_8_null_4,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-7_8_null_5,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-7_8_null_6,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-7_8_null_7,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-7_8_null_8,NEXUS_5,1.0,de].png | 3 + ...KeyView-Day-7_8_null_9,NEXUS_5,1.0,de].png | 3 + ...wChange-Day-5_6_null_0,NEXUS_5,1.0,de].png | 3 - ...wChange-Day-5_6_null_1,NEXUS_5,1.0,de].png | 3 - ...wChange-Day-5_6_null_2,NEXUS_5,1.0,de].png | 3 - ...wChange-Day-5_6_null_3,NEXUS_5,1.0,de].png | 3 - ...wChange-Day-6_7_null_0,NEXUS_5,1.0,de].png | 3 + ...wChange-Day-6_7_null_1,NEXUS_5,1.0,de].png | 3 + ...wChange-Day-6_7_null_2,NEXUS_5,1.0,de].png | 3 + ...wChange-Day-6_7_null_3,NEXUS_5,1.0,de].png | 3 + ...Change-Day-6_7_null_4,NEXUS_5,1.0,de].png} | 0 ...tupView-Day-4_5_null_0,NEXUS_5,1.0,de].png | 3 - ...tupView-Day-4_5_null_1,NEXUS_5,1.0,de].png | 3 - ...tupView-Day-4_5_null_2,NEXUS_5,1.0,de].png | 3 - ...tupView-Day-4_5_null_3,NEXUS_5,1.0,de].png | 3 - ...tupView-Day-5_6_null_0,NEXUS_5,1.0,de].png | 3 + ...tupView-Day-5_6_null_1,NEXUS_5,1.0,de].png | 3 + ...tupView-Day-5_6_null_2,NEXUS_5,1.0,de].png | 3 + ...tupView-Day-5_6_null_3,NEXUS_5,1.0,de].png | 3 + ...upView-Day-5_6_null_4,NEXUS_5,1.0,de].png} | 0 ...OutView-Day-0_1_null_0,NEXUS_5,1.0,de].png | 4 +- ...ionView-Day-0_1_null_0,NEXUS_5,1.0,de].png | 4 +- ...ionView-Day-0_1_null_1,NEXUS_5,1.0,de].png | 4 +- ...ionView-Day-0_1_null_2,NEXUS_5,1.0,de].png | 4 +- ...ionView-Day-0_1_null_3,NEXUS_5,1.0,de].png | 4 +- ...ionView-Day-0_1_null_4,NEXUS_5,1.0,de].png | 4 +- ...ionView-Day-0_1_null_5,NEXUS_5,1.0,de].png | 4 +- ...ionView-Day-0_1_null_6,NEXUS_5,1.0,de].png | 4 +- ...ionView-Day-0_1_null_7,NEXUS_5,1.0,de].png | 4 +- ...ionView-Day-0_1_null_8,NEXUS_5,1.0,de].png | 3 + ...ionView-Day-0_1_null_9,NEXUS_5,1.0,de].png | 3 + screenshots/html/data.js | 990 +++++++++--------- 161 files changed, 892 insertions(+), 674 deletions(-) create mode 100644 features/joinroom/impl/src/main/res/values-be/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-cs/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-de/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-fr/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-hu/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-ru/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-sk/translations.xml rename screenshots/de/{ui_T_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,de].png => ui_T_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,de].png} (100%) create mode 100644 screenshots/de/ui_T_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_3,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_9,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_3,NEXUS_5,1.0,de].png rename screenshots/de/{ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_0,NEXUS_5,1.0,de].png => ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_0,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_1,NEXUS_5,1.0,de].png => ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_1,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_2,NEXUS_5,1.0,de].png => ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_2,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_3,NEXUS_5,1.0,de].png => ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_3,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_4,NEXUS_5,1.0,de].png => ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_4,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_0,NEXUS_5,1.0,de].png => ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_0,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_1,NEXUS_5,1.0,de].png => ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_1,NEXUS_5,1.0,de].png} (100%) create mode 100644 screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_2,NEXUS_5,1.0,de].png rename screenshots/de/{ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_2,NEXUS_5,1.0,de].png => ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_3,NEXUS_5,1.0,de].png} (100%) create mode 100644 screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_4,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_5,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_6,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_3,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_4,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_5,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_null_PendingMemberRowWithLongName-Day-10_11_null,NEXUS_5,1.0,de].png rename screenshots/de/{ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_0,NEXUS_5,1.0,de].png => ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_0,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_1,NEXUS_5,1.0,de].png => ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_1,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_2,NEXUS_5,1.0,de].png => ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_2,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_3,NEXUS_5,1.0,de].png => ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_3,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_4,NEXUS_5,1.0,de].png => ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_4,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_5,NEXUS_5,1.0,de].png => ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_5,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_6,NEXUS_5,1.0,de].png => ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_6,NEXUS_5,1.0,de].png} (100%) create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.createkey_CreateNewRecoveryKeyView_null_CreateNewRecoveryKeyView-Day-0_1_null,NEXUS_5,1.0,de].png rename screenshots/de/{ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_0,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_0,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_1,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_1,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_2,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_2,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_3,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_3,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_0,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_0,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_1,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_1,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_2,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_2,NEXUS_5,1.0,de].png} (100%) delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_0,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_1,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_2,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_3,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_0,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_1,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_2,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_3,NEXUS_5,1.0,de].png rename screenshots/de/{ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_0,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_0,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_1,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_1,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_2,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_2,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_3,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_3,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_4,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_4,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_5,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_5,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_6,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_6,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_7,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_7,NEXUS_5,1.0,de].png} (100%) rename screenshots/de/{ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_8,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_8,NEXUS_5,1.0,de].png} (100%) delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_0,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_1,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_10,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_11,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_2,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_3,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_4,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_5,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_6,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_7,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_8,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_9,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_0,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_1,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_10,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_11,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_2,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_3,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_4,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_5,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_6,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_7,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_8,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_9,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_0,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_1,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_2,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_3,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_0,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_1,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_2,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_3,NEXUS_5,1.0,de].png rename screenshots/de/{ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_4,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_4,NEXUS_5,1.0,de].png} (100%) delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_0,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_1,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_2,NEXUS_5,1.0,de].png delete mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_3,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_0,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_1,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_2,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_3,NEXUS_5,1.0,de].png rename screenshots/de/{ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_4,NEXUS_5,1.0,de].png => ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_4,NEXUS_5,1.0,de].png} (100%) create mode 100644 screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_8,NEXUS_5,1.0,de].png create mode 100644 screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_9,NEXUS_5,1.0,de].png diff --git a/features/createroom/impl/src/main/res/values-ru/translations.xml b/features/createroom/impl/src/main/res/values-ru/translations.xml index f6da7fffa0..42028b98f7 100644 --- a/features/createroom/impl/src/main/res/values-ru/translations.xml +++ b/features/createroom/impl/src/main/res/values-ru/translations.xml @@ -1,7 +1,7 @@ "Новая комната" - "Пригласить друзей" + "Пригласить в комнату" "Произошла ошибка при создании комнаты" "Сообщения в этой комнате зашифрованы. Отключить шифрование позже будет невозможно." "Приватная комната (только по приглашению)" diff --git a/features/ftue/impl/src/main/res/values-be/translations.xml b/features/ftue/impl/src/main/res/values-be/translations.xml index 0079bcf36d..f53a87c797 100644 --- a/features/ftue/impl/src/main/res/values-be/translations.xml +++ b/features/ftue/impl/src/main/res/values-be/translations.xml @@ -3,6 +3,14 @@ "Вы можаце змяніць налады пазней." "Дазвольце апавяшчэнні і ніколі не прапускайце іх" "Устанаўленне злучэння" + "Не атрымалася ўсталяваць бяспечнае злучэнне з новай прыладай. Існуючыя прылады па-ранейшаму ў бяспецы, і вам не трэба турбавацца пра іх." + "Што зараз?" + "Паспрабуйце зноў увайсці ў сістэму з дапамогай QR-кода, калі гэта была сеткавая праблема" + "Калі вы сутыкнуліся з той жа праблемай, паспрабуйце іншую сетку Wi-Fi або скарыстайцеся мабільнымі дадзенымі замест Wi-Fi." + "Калі гэта не дапамагло, увайдзіце ўручную" + "Злучэнне небяспечнае" + "Вам будзе прапанавана ўвесці дзве лічбы, паказаныя ніжэй." + "Увядзіце нумар на прыладзе" "Адкрыйце %1$s на настольнай прыладзе" "Націсніце на свой аватар" "Выберыце %1$s" @@ -13,7 +21,15 @@ "Выкарыстоўвайце QR-код, паказаны на іншай прыладзе." "Паўтарыць спробу" "Няправільны QR-код" + "Перайсці ў налады камеры" + "Каб працягнуць, вам неабходна дазволіць Element выкарыстоўваць камеру вашай прылады." + "Дазвольце доступ да камеры для сканавання QR-кода" "Сканаваць QR-код" + "Пачаць спачатку" + "Адбылася нечаканая памылка. Калі ласка, паспрабуйце яшчэ раз." + "У чаканні іншай прылады" + "Ваш правайдэр уліковага запісу можа запытаць наступны код для праверкі ўваходу." + "Ваш код спраўджання" "Званкі, апытанні, пошук і многае іншае будзе дададзена пазней у гэтым годзе." "Гісторыя паведамленняў для зашыфраваных пакояў пакуль недаступна." "Мы будзем рады пачуць вашае меркаванне, паведаміце нам аб гэтым праз старонку налад." diff --git a/features/ftue/impl/src/main/res/values-bg/translations.xml b/features/ftue/impl/src/main/res/values-bg/translations.xml index 22370ab1c5..d762eecfdd 100644 --- a/features/ftue/impl/src/main/res/values-bg/translations.xml +++ b/features/ftue/impl/src/main/res/values-bg/translations.xml @@ -2,6 +2,7 @@ "Можете да промените настройките си по-късно." "Разрешете известията и никога не пропускайте съобщение" + "Повторен опит" "Хронологията на съобщенията за шифровани стаи все още не е налична." "Добре дошли в %1$s!" diff --git a/features/ftue/impl/src/main/res/values-cs/translations.xml b/features/ftue/impl/src/main/res/values-cs/translations.xml index bc262cf2b4..5f41da6de7 100644 --- a/features/ftue/impl/src/main/res/values-cs/translations.xml +++ b/features/ftue/impl/src/main/res/values-cs/translations.xml @@ -2,6 +2,34 @@ "Nastavení můžete později změnit." "Povolte oznámení a nezmeškejte žádnou zprávu" + "Navazování spojení" + "K novému zařízení se nepodařilo navázat bezpečné připojení. Vaše stávající zařízení jsou stále v bezpečí a nemusíte se o ně obávat." + "Co teď?" + "Zkuste se znovu přihlásit pomocí QR kódu v případě, že se jednalo o problém se sítí" + "Pokud narazíte na stejný problém, zkuste jinou síť wifi nebo použijte mobilní data místo wifi" + "Pokud to nefunguje, přihlaste se ručně" + "Připojení není zabezpečené" + "Budete požádáni o zadání dvou níže uvedených číslic." + "Zadejte číslo na svém zařízení" + "Otevřete %1$s na stolním počítači" + "Klikněte na svůj avatar" + "Vybrat %1$s" + "\"Připojit nové zařízení\"" + "Vybrat %1$s" + "\"Zobrazit QR kód\"" + "Otevřete %1$s na jiném zařízení pro získání QR kódu" + "Použijte QR kód zobrazený na druhém zařízení." + "Zkusit znovu" + "Špatný QR kód" + "Přejděte na nastavení fotoaparátu" + "Abyste mohli pokračovat, musíte aplikaci Element udělit povolení k použití kamery vašeho zařízení." + "Povolte přístup k fotoaparátu a naskenujte QR kód" + "Naskenujte QR kód" + "Začít znovu" + "Vyskytla se neočekávaná chyba. Prosím zkuste to znovu." + "Čekání na vaše další zařízení" + "Váš poskytovatel účtu může požádat o následující kód pro ověření přihlášení." + "Váš ověřovací kód" "Hovory, hlasování, vyhledávání a další budou přidány koncem tohoto roku." "Historie zpráv šifrovaných místností nebude v této aktualizaci k dispozici." "Rádi bychom se od vás dozvěděli, co si o tom myslíte, dejte nám vědět prostřednictvím stránky s nastavením." diff --git a/features/ftue/impl/src/main/res/values-de/translations.xml b/features/ftue/impl/src/main/res/values-de/translations.xml index e647e37686..e7ea08fbfb 100644 --- a/features/ftue/impl/src/main/res/values-de/translations.xml +++ b/features/ftue/impl/src/main/res/values-de/translations.xml @@ -2,6 +2,13 @@ "Du kannst deine Einstellungen später ändern." "Erlaube Benachrichtigungen und verpasse keine Nachricht" + "Verbindung aufbauen" + "Es konnte keine sichere Verbindung zu dem neuen Gerät hergestellt werden." + "Und jetzt?" + "Versuche, dich erneut mit einem QR-Code anzumelden, falls dies ein Netzwerkproblem war." + "Wenn das Problem bestehen bleibt, versuche es mit einem anderen WLAN-Netzwerk oder verwende deine mobilen Daten statt WLAN." + "Wenn das nicht funktioniert, melde dich manuell an" + "Die Verbindung ist nicht sicher" "%1$s auf einem Desktop-Gerät öffnen" "Klick auf deinen Avatar" "Wähle %1$s" @@ -9,6 +16,15 @@ "Wähle %1$s" "\"QR-Code anzeigen\"" "Öffne %1$s auf einem anderen Gerät, um den QR-Code zu erhalten" + "Verwende den QR-Code, der auf dem anderen Gerät angezeigt wird." + "Erneut versuchen" + "Falscher QR-Code" + "Gehe zu den Kameraeinstellungen" + "Du musst Element die Erlaubnis erteilen, die Kamera deines Geräts zu verwenden, um fortzufahren." + "Erlaube Zugriff auf die Kamera zum Scannen des QR-Codes" + "QR-Code scannen" + "Neu beginnen" + "Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es erneut." "Anrufe, Umfragen, Suchfunktionen und mehr werden im Laufe des Jahres hinzugefügt." "Der Nachrichtenverlauf für verschlüsselte Räume wird in diesem Update nicht verfügbar sein." "Wir würden uns freuen, von dir zu hören. Teile uns deine Meinung über die Einstellungsseite mit." diff --git a/features/ftue/impl/src/main/res/values-es/translations.xml b/features/ftue/impl/src/main/res/values-es/translations.xml index 6a3224c531..8f366558d1 100644 --- a/features/ftue/impl/src/main/res/values-es/translations.xml +++ b/features/ftue/impl/src/main/res/values-es/translations.xml @@ -2,6 +2,7 @@ "Puedes cambiar la configuración más tarde." "Activa las notificaciones y nunca te pierdas un mensaje" + "Inténtalo de nuevo" "Las llamadas, las encuestas, la búsqueda y más se agregarán más adelante este año." "El historial de mensajes de las salas cifradas aún no está disponible." "Nos encantaría saber de ti, haznos saber lo que piensas a través de la página de configuración." diff --git a/features/ftue/impl/src/main/res/values-fr/translations.xml b/features/ftue/impl/src/main/res/values-fr/translations.xml index cc2809b4a8..8caf493584 100644 --- a/features/ftue/impl/src/main/res/values-fr/translations.xml +++ b/features/ftue/impl/src/main/res/values-fr/translations.xml @@ -11,7 +11,7 @@ "“Afficher le QR code”" "Ouvrez %1$s sur un autre appareil pour obtenir le QR code" "Scannez le QR code affiché sur l’autre appareil." - "Réessayer" + "Essayer à nouveau" "QR code erroné" "Scannez le QR code" "Les appels, les sondages, les recherches et plus encore seront ajoutés plus tard cette année." diff --git a/features/ftue/impl/src/main/res/values-hu/translations.xml b/features/ftue/impl/src/main/res/values-hu/translations.xml index 6a7acab0a4..f3b101517a 100644 --- a/features/ftue/impl/src/main/res/values-hu/translations.xml +++ b/features/ftue/impl/src/main/res/values-hu/translations.xml @@ -2,6 +2,29 @@ "A beállításokat később is módosíthatja." "Értesítések engedélyezése, hogy soha ne maradjon le egyetlen üzenetről sem" + "Kapcsolat létesítése" + "Nem sikerült biztonságos kapcsolatot létesíteni az új eszközzel. A meglévő eszközei továbbra is biztonságban vannak, és nem kell aggódnia miattuk." + "Most mi lesz?" + "Próbáljon meg újra bejelentkezni egy QR-kóddal, ha ez hálózati probléma volt." + "Ha ugyanezzel a problémával találkozik, próbálkozzon másik Wi-Fi-hálózattal, vagy a Wi-Fi helyett használja a mobil-adatkapcsolatát" + "Ha ez nem működik, jelentkezzen be kézileg" + "A kapcsolat nem biztonságos" + "Nyissa meg az %1$set egy asztali eszközön" + "Kattintson a profilképére" + "Válassza ezt: %1$s" + "„Új eszköz összekapcsolása”" + "Válassza ezt: %1$s" + "„QR-kód megjelenítése”" + "Nyissa meg az %1$set egy másik eszközön a QR-kód lekéréséhez." + "Használja a másik eszközön látható QR-kódot." + "Próbálja újra" + "Hibás QR-kód" + "Ugrás a kamerabeállításokhoz" + "A folytatáshoz engedélyeznie kell, hogy az Element használhassa az eszköz kameráját." + "Engedélyezze a kamera elérését a QR-kód beolvasásához" + "Olvassa be a QR-kódot" + "Újrakezdés" + "Váratlan hiba történt. Próbálja meg újra." "A hívások, szavazások, keresések és egyebek az év további részében kerülnek hozzáadásra." "A titkosított szobák üzenetelőzményei nem lesznek elérhetők ebben a frissítésben." "Szeretnénk hallani a véleményét, ossza meg velünk a beállítások oldalon." diff --git a/features/ftue/impl/src/main/res/values-in/translations.xml b/features/ftue/impl/src/main/res/values-in/translations.xml index 56c4b86fe3..bc2c07e6ea 100644 --- a/features/ftue/impl/src/main/res/values-in/translations.xml +++ b/features/ftue/impl/src/main/res/values-in/translations.xml @@ -2,6 +2,7 @@ "Anda dapat mengubah pengaturan Anda nanti." "Izinkan pemberitahuan dan jangan pernah melewatkan pesan" + "Membuat koneksi" "Buka %1$s di perangkat desktop" "Klik pada avatar Anda" "Pilih %1$s" @@ -9,6 +10,10 @@ "Pilih %1$s" "“Tampilkan kode QR”" "Buka %1$s di perangkat lain untuk mendapatkan kode QR" + "Gunakan kode QR yang ditampilkan di perangkat lain." + "Coba lagi" + "Kode QR salah" + "Pindai kode QR" "Panggilan, pemungutan suara, pencarian, dan lainnya akan ditambahkan di tahun ini." "Riwayat pesan untuk ruangan terenkripsi tidak akan tersedia dalam pembaruan ini." "Kami ingin mendengar dari Anda, beri tahu kami pendapat Anda melalui halaman pengaturan." diff --git a/features/ftue/impl/src/main/res/values-it/translations.xml b/features/ftue/impl/src/main/res/values-it/translations.xml index eaff5216dc..8c253c8c5a 100644 --- a/features/ftue/impl/src/main/res/values-it/translations.xml +++ b/features/ftue/impl/src/main/res/values-it/translations.xml @@ -2,6 +2,7 @@ "Potrai modificare le tue impostazioni in seguito." "Consenti le notifiche e non perdere mai un messaggio" + "Riprova" "Chiamate, sondaggi, ricerche e altro ancora saranno aggiunti nel corso dell\'anno." "La cronologia dei messaggi per le stanze crittografate non è ancora disponibile." "Ci piacerebbe sentire il tuo parere, facci sapere cosa ne pensi tramite la pagina delle impostazioni." diff --git a/features/ftue/impl/src/main/res/values-ro/translations.xml b/features/ftue/impl/src/main/res/values-ro/translations.xml index b89537903d..492e333fe2 100644 --- a/features/ftue/impl/src/main/res/values-ro/translations.xml +++ b/features/ftue/impl/src/main/res/values-ro/translations.xml @@ -2,6 +2,7 @@ "Puteți modifica setările mai târziu." "Permiteți notificările și nu pierdeți niciodată un mesaj" + "Încercați din nou" "Apelurile, sondajele, căutare și multe altele vor fi adăugate în cursul acestui an." "Istoricul mesajelor pentru camerele criptate nu va fi disponibil în această actualizare." "Ne-ar plăcea să auzim de la dumneavoastră, spuneți-ne ce părere aveți prin intermediul paginii de setări." diff --git a/features/ftue/impl/src/main/res/values-ru/translations.xml b/features/ftue/impl/src/main/res/values-ru/translations.xml index 6dc9c5c543..e9eeef5329 100644 --- a/features/ftue/impl/src/main/res/values-ru/translations.xml +++ b/features/ftue/impl/src/main/res/values-ru/translations.xml @@ -2,6 +2,13 @@ "Вы можете изменить настройки позже." "Разрешите уведомления и никогда не пропустите сообщение" + "Установление соединения" + "Не удалось установить безопасное соединение с новым устройством. Существующие устройства по-прежнему в безопасности, и вам не нужно беспокоиться о них." + "Что теперь?" + "Попробуйте снова войти в систему с помощью QR-кода, если это была сетевая проблема" + "Если вы столкнулись с той же проблемой, попробуйте сменить точку доступа Wi-Fi или используйте мобильные данные" + "Если это не помогло, войдите вручную" + "Соединение не защищено" "Откройте %1$s на настольном устройстве" "Нажмите на свое изображение" "Выбрать %1$s" @@ -9,6 +16,15 @@ "Выбрать %1$s" "\"Показать QR-код\"" "Откройте %1$s на другом устройстве, чтобы получить QR-код" + "Используйте QR-код, показанный на другом устройстве." + "Повторить попытку" + "Неверный QR-код" + "Перейдите в настройки камеры" + "Чтобы продолжить, вам необходимо разрешить Element использовать камеру вашего устройства." + "Разрешите доступ к камере для сканирования QR-кода" + "Сканировать QR-код" + "Начать заново" + "Произошла непредвиденная ошибка. Пожалуйста, попробуйте еще раз." "Звонки, опросы, поиск и многое другое будут добавлены позже в этом году." "История сообщений для зашифрованных комнат в этом обновлении будет недоступна." "Мы будем рады услышать ваше мнение, сообщите нам об этом через страницу настроек." diff --git a/features/ftue/impl/src/main/res/values-sk/translations.xml b/features/ftue/impl/src/main/res/values-sk/translations.xml index 7dd1d5e867..846d767df0 100644 --- a/features/ftue/impl/src/main/res/values-sk/translations.xml +++ b/features/ftue/impl/src/main/res/values-sk/translations.xml @@ -2,6 +2,15 @@ "Svoje nastavenia môžete neskôr zmeniť." "Povoľte oznámenia a nikdy nezmeškajte žiadnu správu" + "Nadväzovanie spojenia" + "K novému zariadeniu sa nepodarilo vytvoriť bezpečné pripojenie. Vaše existujúce zariadenia sú stále v bezpečí a nemusíte sa o ne obávať." + "Čo teraz?" + "Skúste sa znova prihlásiť pomocou QR kódu v prípade, že ide o problém so sieťou" + "Ak narazíte na rovnaký problém, vyskúšajte inú sieť Wi-Fi alebo namiesto siete Wi-Fi použite mobilné dáta" + "Ak to nefunguje, prihláste sa manuálne" + "Pripojenie nie je bezpečené" + "Budete vyzvaní na zadanie dvoch číslic uvedených nižšie." + "Zadajte číslo na svojom zariadení" "Otvorte %1$s na stolnom zariadení" "Kliknite na svoj obrázok" "Vyberte %1$s" @@ -9,6 +18,18 @@ "Vyberte %1$s" "„Zobraziť QR kód“" "Ak chcete získať QR kód, otvorte %1$s na inom zariadení" + "Použite QR kód zobrazený na druhom zariadení." + "Skúste to znova" + "Nesprávny QR kód" + "Prejsť na nastavenia fotoaparátu" + "Ak chcete pokračovať, musíte udeliť povolenie aplikácii Element používať fotoaparát vášho zariadenia." + "Povoľte prístup k fotoaparátu na naskenovanie QR kódu" + "Naskenovať QR kód" + "Začať odznova" + "Vyskytla sa neočakávaná chyba. Prosím, skúste to znova." + "Čaká sa na vaše druhé zariadenie" + "Váš poskytovateľ účtu môže požiadať o nasledujúci kód na overenie prihlásenia." + "Váš overovací kód" "Hovory, ankety, vyhľadávanie a ďalšie funkcie pribudnú neskôr v tomto roku." "História správ pre zašifrované miestnosti nebude v tejto aktualizácii k dispozícii." "Radi by sme od vás počuli, dajte nám vedieť, čo si myslíte, prostredníctvom stránky nastavení." diff --git a/features/ftue/impl/src/main/res/values-uk/translations.xml b/features/ftue/impl/src/main/res/values-uk/translations.xml index 53909599b2..f9a72b34af 100644 --- a/features/ftue/impl/src/main/res/values-uk/translations.xml +++ b/features/ftue/impl/src/main/res/values-uk/translations.xml @@ -2,6 +2,7 @@ "Ви можете змінити свої налаштування пізніше." "Дозволити сповіщення і ніколи не пропускати повідомлення" + "Спробуйте ще раз" "Дзвінки, опитування, пошук тощо будуть додані пізніше цього року." "Історія повідомлень для зашифрованих кімнат ще недоступна." "Ми хотіли б почути вас, розкажіть нам ваші враження та ідеї щодо застосунку на сторінці налаштувань." diff --git a/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml b/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml index 8e5d5e3109..51947ca25b 100644 --- a/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml @@ -1,5 +1,6 @@ + "再試一次" "通話、投票、搜尋等更多功能將在今年登場。" "在這次的更新,您無法查看聊天室內被加密的歷史訊息。" "我們很樂意聽取您的意見,請到設定頁面告訴我們您的想法。" diff --git a/features/ftue/impl/src/main/res/values/localazy.xml b/features/ftue/impl/src/main/res/values/localazy.xml index 8c43ef0a81..5257271845 100644 --- a/features/ftue/impl/src/main/res/values/localazy.xml +++ b/features/ftue/impl/src/main/res/values/localazy.xml @@ -3,6 +3,14 @@ "You can change your settings later." "Allow notifications and never miss a message" "Establishing connection" + "A secure connection could not be made to the new device. Your existing devices are still safe and you don\'t need to worry about them." + "What now?" + "Try signing in again with a QR code in case this was a network problem" + "If you encounter the same problem, try a different wifi network or use your mobile data instead of wifi" + "If that doesn’t work, sign in manually" + "Connection not secure" + "You’ll be asked to enter the two digits shown below." + "Enter number on your device" "Open %1$s on a desktop device" "Click on your avatar" "Select %1$s" @@ -11,9 +19,17 @@ "“Show QR code”" "Open %1$s on another device to get the QR code" "Use the QR code shown on the other device." - "Try Again" + "Try again" "Wrong QR code" + "Go to camera settings" + "You need to give permission for Element to use your device’s camera in order to continue." + "Allow camera access to scan the QR code" "Scan the QR code" + "Start over" + "An unexpected error occurred. Please try again." + "Waiting for your other device" + "Your account provider may ask for the following code to verify the sign in." + "Your verification code" "Calls, polls, search and more will be added later this year." "Message history for encrypted rooms isn’t available yet." "We’d love to hear from you, let us know what you think via the settings page." diff --git a/features/joinroom/impl/src/main/res/values-be/translations.xml b/features/joinroom/impl/src/main/res/values-be/translations.xml new file mode 100644 index 0000000000..f02d8ff94a --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-be/translations.xml @@ -0,0 +1,9 @@ + + + "Далучыцца да пакоя" + "Націсніце, каб далучыцца" + "Націсніце кнопку ніжэй, і адміністратар пакоя атрымае апавяшчэнне. Вы зможаце далучыцца да размовы пасля зацвярджэння." + "Вы павінны быць удзельнікам гэтага пакоя каб прагледзець гісторыю паведамленняў." + "Вы хочаце далучыцца да гэтага пакоя?" + "Папярэдні прагляд недаступны" + diff --git a/features/joinroom/impl/src/main/res/values-cs/translations.xml b/features/joinroom/impl/src/main/res/values-cs/translations.xml new file mode 100644 index 0000000000..9f175974ad --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-cs/translations.xml @@ -0,0 +1,9 @@ + + + "Připojit se do místnosti" + "Zaklepejte a připojte se" + "Klikněte na tlačítko níže a správce místnosti bude informován. Po schválení se budete moci připojit ke konverzaci." + "Pro zobrazení historie zpráv musíte být členem této místnosti." + "Chcete se připojit k této místnosti?" + "Náhled není k dispozici" + diff --git a/features/joinroom/impl/src/main/res/values-de/translations.xml b/features/joinroom/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..c4aefdc126 --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,9 @@ + + + "Raum beitreten" + "Anklopfen" + "Klopfe an um einen Raumadministrator zu benachrichtigen. Nach der Freigabe kannst du dich an der Unterhaltung beteiligen." + "Du musst Mitglied in diesem Raum sein, um den Nachrichtenverlauf zu sehen." + "Willst du diesem Raum beitreten?" + "Vorschau nicht verfügbar" + diff --git a/features/joinroom/impl/src/main/res/values-fr/translations.xml b/features/joinroom/impl/src/main/res/values-fr/translations.xml new file mode 100644 index 0000000000..b2e56edb23 --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-fr/translations.xml @@ -0,0 +1,9 @@ + + + "Rejoindre" + "Demander à joindre" + "Cliquez ci-dessous et un administrateur sera prévenu. Une fois votre demande approuvée, pour pourrez rejoindre la discussion." + "Vous devez être un membre du salon pour pouvoir lire l’historique des messages." + "Vous souhaitez rejoindre ce salon?" + "La prévisualisation n’est pas disponible" + diff --git a/features/joinroom/impl/src/main/res/values-hu/translations.xml b/features/joinroom/impl/src/main/res/values-hu/translations.xml new file mode 100644 index 0000000000..505fe1a955 --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-hu/translations.xml @@ -0,0 +1,9 @@ + + + "Csatlakozás a szobához" + "Kopogtasson a csatlakozáshoz" + "Kattintson az alábbi gombra, és a szoba adminisztrátora értesítést kap. A jóváhagyást követően csatlakozhat a beszélgetéshez." + "Az üzenetelőzmények megtekintéséhez a szoba tagjának kell lennie." + "Csatlakozna ehhez a szobához?" + "Az előnézet nem érhető el" + diff --git a/features/joinroom/impl/src/main/res/values-ru/translations.xml b/features/joinroom/impl/src/main/res/values-ru/translations.xml new file mode 100644 index 0000000000..cec44b1c8c --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-ru/translations.xml @@ -0,0 +1,9 @@ + + + "Присоединиться к комнате" + "Постучите, чтобы присоединиться" + "Нажмите кнопку ниже и администратор комнаты получит уведомление. После одобрения вы сможете присоединиться к обсуждению." + "Вы должны быть участником этой комнаты, чтобы просмотреть историю сообщений." + "Хотите присоединиться к этой комнате?" + "Предварительный просмотр недоступен" + diff --git a/features/joinroom/impl/src/main/res/values-sk/translations.xml b/features/joinroom/impl/src/main/res/values-sk/translations.xml new file mode 100644 index 0000000000..9a6e87c183 --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-sk/translations.xml @@ -0,0 +1,9 @@ + + + "Pripojiť sa do miestnosti" + "Zaklopaním sa pripojíte" + "Kliknite na tlačidlo nižšie a správca miestnosti bude informovaný. Po schválení sa budete môcť pripojiť ku konverzácii." + "Ak chcete zobraziť históriu správ, musíte byť členom tejto miestnosti." + "Chcete sa pripojiť do tejto miestnosti?" + "Náhľad nie je k dispozícii" + diff --git a/features/lockscreen/impl/src/main/res/values-ru/translations.xml b/features/lockscreen/impl/src/main/res/values-ru/translations.xml index f0f5c1ada2..07d4e4d3a6 100644 --- a/features/lockscreen/impl/src/main/res/values-ru/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-ru/translations.xml @@ -18,7 +18,7 @@ "Выберите другой PIN-код" "Заблокируйте %1$s, чтобы повысить безопасность ваших чатов. -Выберите что-нибудь незабываемое. Если вы забудете этот PIN-код, вы выйдете из приложения." +Введите что-нибудь незабываемое. Если вы забудете этот PIN-код, вы выйдете из приложения." "Повторите PIN-код" "PIN-коды не совпадают" "Чтобы продолжить, вам необходимо повторно войти в систему и создать новый PIN-код" diff --git a/features/roomdetails/impl/src/main/res/values-be/translations.xml b/features/roomdetails/impl/src/main/res/values-be/translations.xml index 85fb82b96a..3761d90ac4 100644 --- a/features/roomdetails/impl/src/main/res/values-be/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-be/translations.xml @@ -9,7 +9,7 @@ "Пры абнаўленні налад апавяшчэнняў адбылася памылка." "Ваш хатні сервер не падтрымлівае гэтую опцыю ў зашыфраваных пакоях, вы можаце не атрымаць апавяшчэнне ў некаторых пакоях." "Апытанні" - "Толькі для адміністратараў" + "Толькі адміністратары" "Заблакіраваць людзей" "Выдаліць паведамленні" "Усе" @@ -44,7 +44,7 @@ "Рэдагаваць пакой" "Адбылася невядомая памылка, і інфармацыю нельга было змяніць." "Немагчыма абнавіць пакой" - "Паведамленні абаронены замкамі. Толькі ў вас і атрымальнікаў ёсць унікальныя ключы, каб разблакіраваць іх." + "Паведамленні зашыфраваны. Толькі ў вас і ў атрымальнікаў ёсць унікальныя ключы для іх разблакіроўкі." "Шыфраванне паведамленняў уключана" "Пры загрузцы налад апавяшчэнняў адбылася памылка." "Не атрымалася адключыць гук у гэтым пакоі, паўтарыце спробу." @@ -89,7 +89,7 @@ "Мадэратар" "Удзельнікі пакоя" "Разблакіроўка %1$s" - "Дазволіць карыстальніцкую наладу" + "Дазволіць уласную наладу" "Калі гэта ўключыць, ваша налада прадвызначана будзе адменена" "Апавяшчаць мяне ў гэтым чаце для" "Вы можаце змяніць гэта ў %1$s." diff --git a/features/roomdetails/impl/src/main/res/values-ru/translations.xml b/features/roomdetails/impl/src/main/res/values-ru/translations.xml index 9e6b963efb..2cfa24a003 100644 --- a/features/roomdetails/impl/src/main/res/values-ru/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ru/translations.xml @@ -49,7 +49,7 @@ "При загрузке настроек уведомлений произошла ошибка." "Не удалось отключить звук в этой комнате, попробуйте еще раз." "Не удалось включить звук в эту комнату, попробуйте еще раз." - "Пригласить друзей" + "Пригласить в комнату" "Покинуть беседу" "Покинуть комнату" "Пользовательский" diff --git a/features/securebackup/impl/src/main/res/values-hu/translations.xml b/features/securebackup/impl/src/main/res/values-hu/translations.xml index a3fed4e584..944174f434 100644 --- a/features/securebackup/impl/src/main/res/values-hu/translations.xml +++ b/features/securebackup/impl/src/main/res/values-hu/translations.xml @@ -32,7 +32,7 @@ "Győződjön meg arról, hogy senki sem látja ezt a képernyőt!" "Próbálja meg újra megerősíteni a csevegés biztonsági mentéséhez való hozzáférését." "Helytelen helyreállítási kulcs" - "Ha van helyreállítási kulcsa vagy titkos jelmondata/kulcsa, akkor ez is fog működni." + "Ha van biztonsági kulcsa vagy biztonsági jelmondata, akkor ez is fog működni." "Helyreállítási kulcs vagy jelkód" "Megadás…" "Helyreállítási kulcs megerősítve" diff --git a/libraries/ui-strings/src/main/res/values-be/translations.xml b/libraries/ui-strings/src/main/res/values-be/translations.xml index 31ce0e9ffe..01a127ae5d 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -202,8 +202,9 @@ "Сервер не падтрымліваецца" "URL-адрас сервера" "Налады" - "Абагуленае месцазнаходжанне" + "Абагулена месцазнаходжанне" "Выхад" + "Нешта пайшло не так" "Пачатак чата…" "Стыкер" "Поспех" @@ -249,12 +250,6 @@ "Гэй, пагавары са мной у %1$s: %2$s" "%1$s Android" "Паведаміць аб памылцы з дапамогай Rageshake" - "Далучыцца да пакоя" - "Націсніце, каб далучыцца" - "Націсніце кнопку ніжэй, і адміністратар пакоя атрымае апавяшчэнне. Вы зможаце далучыцца да размовы пасля зацвярджэння." - "Вы павінны быць удзельнікам гэтага пакоя каб прагледзець гісторыю паведамленняў." - "Вы хочаце далучыцца да гэтага пакоя?" - "Папярэдні прагляд недаступны" "Не ўдалося выбраць носьбіт, паўтарыце спробу." "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз." "Не атрымалася загрузіць медыяфайлы, паспрабуйце яшчэ раз." diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index b92077b657..e6b648d731 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -204,6 +204,7 @@ "Nastavení" "Sdílená poloha" "Odhlašování" + "Něco se pokazilo" "Zahajování chatu…" "Nálepka" "Úspěch" 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 9de81a7beb..095374783e 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -202,6 +202,7 @@ "Einstellungen" "Geteilter Standort" "Abmelden" + "Es ist ein Fehler aufgetreten." "Chat wird gestartet…" "Sticker" "Erfolg" @@ -247,12 +248,6 @@ "Hey, sprich mit mir auf %1$s: %2$s" "%1$s Android" "Schüttel heftig zum Melden von Fehlern" - "Raum beitreten" - "Anklopfen" - "Klopfe an um einen Raumadministrator zu benachrichtigen. Nach der Freigabe kannst du dich an der Unterhaltung beteiligen." - "Du musst Mitglied in diesem Raum sein, um den Nachrichtenverlauf zu sehen." - "Willst du diesem Raum beitreten?" - "Vorschau nicht verfügbar" "Medienauswahl fehlgeschlagen, bitte versuche es erneut." "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut." "Das Hochladen der Medien ist fehlgeschlagen. Bitte versuche es erneut." diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index 037634e46b..6ee43d0b78 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -200,6 +200,7 @@ "Paramètres" "Position partagée" "Déconnexion" + "Une erreur s’est produite" "Création de la discussion…" "Autocollant" "Succès" @@ -245,12 +246,6 @@ "Salut, parle-moi sur %1$s : %2$s" "%1$s Android" "Rageshake pour signaler un problème" - "Rejoindre" - "Demander à joindre" - "Cliquez ci-dessous et un administrateur sera prévenu. Une fois votre demande approuvée, pour pourrez rejoindre la discussion." - "Vous devez être un membre du salon pour pouvoir lire l’historique des messages." - "Vous souhaitez rejoindre ce salon?" - "La prévisualisation n’est pas disponible" "Échec de la sélection du média, veuillez réessayer." "Échec du traitement des médias à télécharger, veuillez réessayer." "Échec du téléchargement du média, veuillez réessayer." diff --git a/libraries/ui-strings/src/main/res/values-hu/translations.xml b/libraries/ui-strings/src/main/res/values-hu/translations.xml index aed5aefacf..5506714d7a 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -200,6 +200,7 @@ "Beállítások" "Megosztott tartózkodási hely" "Kijelentkezés" + "Valamilyen hiba történt" "Csevegés megkezdése…" "Matrica" "Sikeres" diff --git a/libraries/ui-strings/src/main/res/values-in/translations.xml b/libraries/ui-strings/src/main/res/values-in/translations.xml index 4968a05e1f..fdbf31da25 100644 --- a/libraries/ui-strings/src/main/res/values-in/translations.xml +++ b/libraries/ui-strings/src/main/res/values-in/translations.xml @@ -241,12 +241,6 @@ "Hai, bicaralah dengan saya di %1$s: %2$s" "%1$s Android" "Rageshake untuk melaporkan kutu" - "Gabung dengan ruangan" - "Ketuk untuk bergabung" - "Klik tombol di bawah ini dan administrator kamar akan diberi tahu. Anda akan dapat bergabung dengan percakapan setelah disetujui." - "Anda harus menjadi anggota ruangan ini untuk melihat riwayat pesan." - "Ingin bergabung dengan ruangan ini?" - "Pratinjau tidak tersedia" "Gagal memilih media, silakan coba lagi." "Gagal memproses media untuk diunggah, silakan coba lagi." "Gagal mengunggah media, silakan coba lagi." diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index 054d42b94f..0634590b92 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -62,8 +62,8 @@ "Переслать" "Вернуться" "Пригласить" - "Пригласить друзей" - "Пригласить друзей в %1$s" + "Пригласить в комнату" + "Пригласить в %1$s" "Пригласите пользователей в %1$s" "Приглашения" "Присоединиться" @@ -206,6 +206,7 @@ "Настройки" "Делится местонахождением" "Выход…" + "Что-то пошло не так" "Начало чата…" "Стикер" "Успешно" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index 591b2ad7b8..2b2b6cbf09 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -203,6 +203,7 @@ "Nastavenia" "Zdieľaná poloha" "Odhlasovanie" + "Niečo sa pokazilo" "Spustenie konverzácie…" "Nálepka" "Úspech" @@ -248,12 +249,6 @@ "Ahoj, porozprávajte sa so mnou na %1$s: %2$s" "%1$s Android" "Zúrivo potriasť pre nahlásenie chyby" - "Pripojiť sa do miestnosti" - "Zaklopaním sa pripojíte" - "Kliknite na tlačidlo nižšie a správca miestnosti bude informovaný. Po schválení sa budete môcť pripojiť ku konverzácii." - "Ak chcete zobraziť históriu správ, musíte byť členom tejto miestnosti." - "Chcete sa pripojiť do tejto miestnosti?" - "Náhľad nie je k dispozícii" "Nepodarilo sa vybrať médium, skúste to prosím znova." "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa nahrať médiá, skúste to prosím znova." diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index c927eec7cd..05d6aa1b24 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -200,6 +200,7 @@ "Settings" "Shared location" "Signing out" + "Something went wrong" "Starting chat…" "Sticker" "Success" @@ -245,12 +246,6 @@ "Hey, talk to me on %1$s: %2$s" "%1$s Android" "Rageshake to report bug" - "Join room" - "Knock to join" - "Click the button below and a room administrator will be notified. You’ll be able to join the conversation once approved." - "You must be a member of this room to view the message history." - "Want to join this room?" - "Preview is not available" "Failed selecting media, please try again." "Failed processing media to upload, please try again." "Failed uploading media, please try again." diff --git a/screenshots/de/ui_T_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.analytics.impl_AnalyticsOptInView_null_AnalyticsOptInView-Day-0_1_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.analytics.impl_AnalyticsOptInView_null_AnalyticsOptInView-Day-0_1_null_0,NEXUS_5,1.0,de].png index 0fe9da89f3..d298aa4e56 100644 --- a/screenshots/de/ui_T_t[f.analytics.impl_AnalyticsOptInView_null_AnalyticsOptInView-Day-0_1_null_0,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.analytics.impl_AnalyticsOptInView_null_AnalyticsOptInView-Day-0_1_null_0,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ceaea25d084647a0b2e9849ad0957dae4f79231a52ab6c69da01425497b94428 -size 62282 +oid sha256:7b7c5b18c5dfc18081b4f433d8881b202d5afc1756b87bfc85fd10227e846c17 +size 101352 diff --git a/screenshots/de/ui_T_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_3,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..b502b03592 --- /dev/null +++ b/screenshots/de/ui_T_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_3,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39b63c57c0a74de71bd2784c705d70d67ecabddfbaafc5e70c6801deb5f550d0 +size 47852 diff --git a/screenshots/de/ui_T_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_9,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_9,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..2391c0e554 --- /dev/null +++ b/screenshots/de/ui_T_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_9,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4478fa7cc3173761ba75016b9ceb57709a98ecc133e8a4ea1aefbcdb3870204 +size 40890 diff --git a/screenshots/de/ui_T_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_3,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..116127d285 --- /dev/null +++ b/screenshots/de/ui_T_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_3,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:432e5b0fcd4696b734a86b24a1ce2d5053375e179ebdf803b9871431ddad641b +size 52238 diff --git a/screenshots/de/ui_T_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Day-0_1_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Day-0_1_null_0,NEXUS_5,1.0,de].png index 434ede079b..acc773b3c9 100644 --- a/screenshots/de/ui_T_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Day-0_1_null_0,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Day-0_1_null_0,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a881696b70a7cc2830cc8ba1e4f0cbdc5e2a05733756a4f244a1cda8aff0f61f -size 40167 +oid sha256:02129564d35c10049301639f1813610a37aae588f4e9784660a86f358cf5bc5e +size 76730 diff --git a/screenshots/de/ui_T_t[f.ftue.impl.welcome_WelcomeView_null_WelcomeView-Day-1_2_null,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.ftue.impl.welcome_WelcomeView_null_WelcomeView-Day-1_2_null,NEXUS_5,1.0,de].png index 67a9c7a5ef..b30cd15e24 100644 --- a/screenshots/de/ui_T_t[f.ftue.impl.welcome_WelcomeView_null_WelcomeView-Day-1_2_null,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.ftue.impl.welcome_WelcomeView_null_WelcomeView-Day-1_2_null,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01fbc1c6a66aee09fed370dc316706ecdb179fd0d4873566ffedfb6b93e14bb2 -size 290341 +oid sha256:54d6a23c0b5e1a47fb115b84f3f0d387d4de2c8bed8638f96a41fcb39a0f9016 +size 290319 diff --git a/screenshots/de/ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_0,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_0,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_0,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_1,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_1,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_1,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_2,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_2,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_2,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_3,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_3,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_3,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_4,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_4,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_4,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_0,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_0,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_0,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_1,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_1,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_1,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_2,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..a4e38f9c6c --- /dev/null +++ b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_2,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34a09c8fc14f87ee2d61fbd4ba030dd50649ba92d263c0c5ad76cfcc5655dab1 +size 60091 diff --git a/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_3,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_2,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_3,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_4,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..0bfbb3ce21 --- /dev/null +++ b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_4,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1853c0b025f5ae7596c7632ee0712ad37b2049fcd9e0eb0eb8b7f99049e883e1 +size 60129 diff --git a/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_5,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_5,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..06411f14c4 --- /dev/null +++ b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_5,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73c32078b2589df4821a2d7fe3b22dbd35b525a7f0ce795c77817e03f2d3fa1a +size 45626 diff --git a/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_6,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_6,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..06411f14c4 --- /dev/null +++ b/screenshots/de/ui_T_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_6,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73c32078b2589df4821a2d7fe3b22dbd35b525a7f0ce795c77817e03f2d3fa1a +size 45626 diff --git a/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_3,NEXUS_5,1.0,de].png deleted file mode 100644 index fde8228ed4..0000000000 --- a/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_3,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0cc66a0282234019aecc9b2e42cda9f67479eb0ebb13a04d0bc2f480477002df -size 60163 diff --git a/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_4,NEXUS_5,1.0,de].png deleted file mode 100644 index 045b87b9e6..0000000000 --- a/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_4,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:88d8da7527fe12cbab75ecb959ad84a52e08f3bc8f7bb8f91981c7ab82a03177 -size 50394 diff --git a/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_5,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_5,NEXUS_5,1.0,de].png deleted file mode 100644 index 045b87b9e6..0000000000 --- a/screenshots/de/ui_T_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_5,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:88d8da7527fe12cbab75ecb959ad84a52e08f3bc8f7bb8f91981c7ab82a03177 -size 50394 diff --git a/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_0,NEXUS_5,1.0,de].png index a859307509..2985e96ce6 100644 --- a/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_0,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_0,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1d31bfab05d2b92f4179242e49f0798bbe493c2c9c66bf771857fdb199c74a8 -size 37090 +oid sha256:aa27f5f39f6f3342ca4f82b965184e8757f8323a7f067d7bc4c23c328c7ff9ea +size 37554 diff --git a/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_1,NEXUS_5,1.0,de].png index 13a611a3cc..38e763abcf 100644 --- a/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_1,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_1,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b907b05eaeb9f02aace39b681c14ac05f5a8c6473d6cfe2bf964c5c181259780 -size 36839 +oid sha256:340a03a0cb175cc6f92c210c41dc5c754c612b2fc5ad6bb66ca258739c0335fc +size 37302 diff --git a/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_2,NEXUS_5,1.0,de].png index 8cfa988d2b..d253a16d88 100644 --- a/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_2,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_2,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:574dfd1da16d0a88a4e9dc94b4a84cceea988967f7e2b3e17ed58a4fa961fdc9 -size 38365 +oid sha256:187d55d1554a5af4dafb6201dcd3d89f25ea614e5d3458a58780916fe5c8d2ee +size 38895 diff --git a/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_3,NEXUS_5,1.0,de].png index 95c3ea418d..fd2056ac1b 100644 --- a/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_3,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_3,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40df09ca1bda368f3c1674b56d320ceb7cdfac2be39ee7015d82e25000a3ba6c -size 32929 +oid sha256:0ba3b09d2ec5bc027452f4e88dae2aa392827f7ebcfde6ea6d81bceddb2cd4aa +size 33070 diff --git a/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_4,NEXUS_5,1.0,de].png index ed686864ea..bff6f8406e 100644 --- a/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_4,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_4,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4c3ee331bbf456258a74ee23d19a408683b2de015fe4939ba8f5e3012529cab -size 36838 +oid sha256:fff2a8a24c0f31bbedd4ca6885213f921c585c5b859f5bcc3b798466a1d3c378 +size 36904 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_0,NEXUS_5,1.0,de].png index 9214219bc4..9a04dc1b4c 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_0,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_0,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14b5f48b528b083d9e6cda0ddf9cfbe867a879e4f421634bdfff982202c10e45 -size 21230 +oid sha256:e32908d6030098b21cc79e917068a8ee3afd4c5051ed2eca536470147924f08c +size 18224 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_1,NEXUS_5,1.0,de].png index 34106fd24c..8b2709831f 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_1,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_1,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b61fd9886f100b06e8e055f2d6df48efb46197bc7d91296c88244bb640facb7 -size 22992 +oid sha256:df76452cb18791c0d06229fb9acb1b8964dbc6ed61bb6308daadbd57bd9fab08 +size 79032 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_10,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_10,NEXUS_5,1.0,de].png index acbd7d5594..521b79a0a7 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_10,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_10,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:978f8d20f848aa640b876658a1ddb6470dcb361aa5c714fa62ac59284c86e5f6 -size 59009 +oid sha256:470cb6688022146dd58fe90db6172bd51ddddfd0bcc749601c2ad9b52ffb6f13 +size 59284 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_2,NEXUS_5,1.0,de].png index bec09545dc..bc6fdf61b0 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_2,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_2,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:51fd05f8c1fca35f9f3f787c62e653a49bdd3d61f6fe1ef222b3d3aee2e65f22 -size 68802 +oid sha256:8d001460a98fd62286e8d078742b88593dca0b5a58acd170ae2ced4cbc7929c6 +size 72277 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_3,NEXUS_5,1.0,de].png index 2fe73c000a..9c723ed2c8 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_3,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_3,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0b7731493a2f517d79552fafae4747545646d84d3c5cb28d20239b5e68b0d84 -size 68581 +oid sha256:2a5d49bf6b566bef906484d0906712ed45930cef4159bf2447c71c7cb66d5d54 +size 72057 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_4,NEXUS_5,1.0,de].png index ec57faca00..82bdbd0698 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_4,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_4,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7396130d5c5ff31d2f219d382dbd6ae96c9ae0087ef85271b845e2f39ebf0a73 -size 62565 +oid sha256:4ad1175ad17b137d7e256275f06036c162351b3aa65034e703da510b0792f903 +size 66444 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_5,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_5,NEXUS_5,1.0,de].png index a3321355ed..cf0862c342 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_5,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_5,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7d45867c0ca6cb2aa6f6cc3c295fe1b061b53fcdc180b93a00897e1a46f5ca3 -size 16182 +oid sha256:cb67bf76f5f961c512c71c9534b96062d3aa88b4deafec612898e0e7aac7ac19 +size 16174 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_6,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_6,NEXUS_5,1.0,de].png index 98fff0f2ba..d0a5179f28 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_6,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_6,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fccf9edbcb4fcb825ad0b89ed229b134951c9eda940f7be89e3c4fa147d5a51 -size 69887 +oid sha256:d1e43a716508869638761d686fcfbdd790af2105069641e7a7af9f97f29d0fbc +size 71402 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_7,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_7,NEXUS_5,1.0,de].png index 4cb6e2ccf9..632c88119c 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_7,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_7,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc8d93d943628b01996913f9286bbc742f3d3ad33a1642289e588caef7c1bac7 -size 72956 +oid sha256:0a9da25fddf7f20e9db2d88eca47a4a8eb74455ae529cf3170f6c5ca0fe6c926 +size 73630 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_8,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_8,NEXUS_5,1.0,de].png index b28495d05f..0b565eb5d1 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_8,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_8,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75af0f62d57347a3cd5bd3350f08eb8d99a5cc57ef6598057d6b709aaf5899f5 -size 61252 +oid sha256:337e6c9b19e8b92ed97cca61448ce3595cf9210724c7bb6c62c85c2bc24955f5 +size 63407 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_9,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_9,NEXUS_5,1.0,de].png index bbc57cf00d..b313c4c9bf 100644 --- a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_9,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_9,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15d5ca56d3ba6c4394c44bd623feda6737ec758d98d37ee5697bb0d70eb682be -size 71213 +oid sha256:7d12f3919123740ecd72ceb4ec4b71813eefe1ee656f4aba786fed01215d8e09 +size 74634 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_null_PendingMemberRowWithLongName-Day-10_11_null,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_null_PendingMemberRowWithLongName-Day-10_11_null,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..f01bbfd24c --- /dev/null +++ b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_null_PendingMemberRowWithLongName-Day-10_11_null,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:625b3503cdb7023ca4d768e3bdd735ed342230fac66d13fb1dfcb22adb875623 +size 16713 diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_0,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_0,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_0,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_1,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_1,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_1,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_2,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_2,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_2,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_3,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_3,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_3,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_4,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_4,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_4,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_5,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_5,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_5,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_5,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_6,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_6,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_6,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_6,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.createkey_CreateNewRecoveryKeyView_null_CreateNewRecoveryKeyView-Day-0_1_null,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.createkey_CreateNewRecoveryKeyView_null_CreateNewRecoveryKeyView-Day-0_1_null,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..974c901c41 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.createkey_CreateNewRecoveryKeyView_null_CreateNewRecoveryKeyView-Day-0_1_null,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84e51e4ef511a2208276f4a3beb6326a80a83d1887568b828147da205a151660 +size 82365 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_0,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_0,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_0,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_1,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_1,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_1,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_2,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_2,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_2,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_3,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_3,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_3,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_0,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_0,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_0,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_1,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_1,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_1,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_2,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_2,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_2,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_0,NEXUS_5,1.0,de].png deleted file mode 100644 index a710f79532..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_0,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:38a94d2276af933d4c123a2a00728db01be7d6665311217ca7f0124612b60105 -size 58662 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_1,NEXUS_5,1.0,de].png deleted file mode 100644 index d89ff64056..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_1,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8e7e7263a120db2e187828203198188a87dd507701dc42b281d1c3d017454f00 -size 70414 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_2,NEXUS_5,1.0,de].png deleted file mode 100644 index 186132354d..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_2,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9fe482de11f11ff7f0bc4050b7ff143497e85ae7c6d12ba73ddfae3c32249e38 -size 68729 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_3,NEXUS_5,1.0,de].png deleted file mode 100644 index e250398dc2..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_3,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:15c41ad7fa311752c3fc7b6d6e27f4f80944c6430fb6f23c659b9d795ec0cca0 -size 56295 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_0,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..a3c2ca65ce --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_0,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91b9724a3d460dbcdd5ea25bcb9aac9ceba18d58621e743e80c7f0583902241e +size 53114 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_1,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..ae4a903e64 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_1,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b2a29995bd4562466e7bb54c7f721c3b41d26b583adca0d32da08c9b57e9ca5e +size 64687 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_2,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..8d21bf7ae3 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_2,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1d20b4e4ab821ad1adee9af1d39b11e52a9a81848cb77ebfbf790bbc7af3722 +size 62961 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_3,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..8197dd01e2 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_3,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f31fa189d99a64b155450927f9d9d5f34bfadb88afcbc1f76faf99a19d6afa19 +size 51530 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_0,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_0,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_0,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_1,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_1,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_1,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_2,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_2,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_2,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_3,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_3,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_3,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_4,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_4,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_4,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_5,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_5,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_5,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_5,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_6,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_6,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_6,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_6,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_7,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_7,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_7,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_7,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_8,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_8,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_8,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_8,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_0,NEXUS_5,1.0,de].png deleted file mode 100644 index 8822a44d49..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_0,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4ee264d6715fe4d8e8c0ff5ba07afcd33409d131d27effa77e07bbdeef47e23b -size 31034 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_1,NEXUS_5,1.0,de].png deleted file mode 100644 index 4741997df4..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_1,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f4001ba3ca38363142f096aa4b7a052a8b7641982994698b5dd3134d0a79b65f -size 27951 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_10,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_10,NEXUS_5,1.0,de].png deleted file mode 100644 index a40adf773a..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_10,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1b1de5b9084a41c3e97d21aeb24ae14f761410084c950946085f69510da0bbc4 -size 39496 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_11,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_11,NEXUS_5,1.0,de].png deleted file mode 100644 index 6c35e48ccb..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_11,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dce9eb56dc9c07027064147cd73adea4625e997575d7c4afaa453ede7c7a383c -size 36921 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_2,NEXUS_5,1.0,de].png deleted file mode 100644 index 793849862c..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_2,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8a736d35d4a326dfa007026ab1fdabf4d0b65c28f0bf2267c707362b55add6d6 -size 29891 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_3,NEXUS_5,1.0,de].png deleted file mode 100644 index 793849862c..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_3,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8a736d35d4a326dfa007026ab1fdabf4d0b65c28f0bf2267c707362b55add6d6 -size 29891 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_4,NEXUS_5,1.0,de].png deleted file mode 100644 index 1f9fc0a2a7..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_4,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3cad5a954b9cfe40b1be19770e9f721d8d8d7f1f86d8c837c770ff4676bdab0c -size 33060 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_5,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_5,NEXUS_5,1.0,de].png deleted file mode 100644 index 4741997df4..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_5,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f4001ba3ca38363142f096aa4b7a052a8b7641982994698b5dd3134d0a79b65f -size 27951 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_6,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_6,NEXUS_5,1.0,de].png deleted file mode 100644 index 793849862c..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_6,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8a736d35d4a326dfa007026ab1fdabf4d0b65c28f0bf2267c707362b55add6d6 -size 29891 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_7,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_7,NEXUS_5,1.0,de].png deleted file mode 100644 index 793849862c..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_7,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8a736d35d4a326dfa007026ab1fdabf4d0b65c28f0bf2267c707362b55add6d6 -size 29891 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_8,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_8,NEXUS_5,1.0,de].png deleted file mode 100644 index 51cf877cf8..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_8,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:994c6c3f0698d90e42bc5db279ad717a30b37a4bdcb068cfa22998f524dcf7aa -size 28167 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_9,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_9,NEXUS_5,1.0,de].png deleted file mode 100644 index c6a3f32d68..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_9,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bd781c1b0b295f8bc18db6ef031f37ad69cb3af4f905bc82859d9678fc43a58c -size 28005 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_0,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..c290043657 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_0,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dde7780e24eb315b8671ada81dfc93397a2c7f324198d66cd17046d12d1ac3e0 +size 29115 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_1,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..041e38b060 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_1,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ca3b63c4d12ef8d6436586043a3fd3cf80203c0c5d37f30c7027a3b11046188 +size 26185 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_10,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_10,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..7d4ed60591 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_10,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89f0f462ac97eebee08e4af07af766e105e148c7a6a2370f9cb997f2b0fb725f +size 33965 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_11,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_11,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..b326828a92 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_11,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f81ae06743d3a7fe9b09724c851dbfee14da8286cda0e0303bc0df35e22f511 +size 31339 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_2,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..d7e0800c88 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_2,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bba005d1b6341246ac3ddc03e1dcd7abecf9f80fca5bbf12e1b88d8a8ff8352d +size 28283 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_3,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..d7e0800c88 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_3,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bba005d1b6341246ac3ddc03e1dcd7abecf9f80fca5bbf12e1b88d8a8ff8352d +size 28283 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_4,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..9edbce8972 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_4,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ffef63d7b63588193e346713f4898bd5b7cf5e8103a9440662f56e7b4897d38 +size 30826 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_5,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_5,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..041e38b060 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_5,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ca3b63c4d12ef8d6436586043a3fd3cf80203c0c5d37f30c7027a3b11046188 +size 26185 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_6,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_6,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..d7e0800c88 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_6,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bba005d1b6341246ac3ddc03e1dcd7abecf9f80fca5bbf12e1b88d8a8ff8352d +size 28283 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_7,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_7,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..d7e0800c88 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_7,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bba005d1b6341246ac3ddc03e1dcd7abecf9f80fca5bbf12e1b88d8a8ff8352d +size 28283 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_8,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_8,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..817e740733 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_8,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0df5c096627be212f807766d74579c1a5465791277ef05a895424085c4e55173 +size 23784 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_9,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_9,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..ffa1a915fe --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_9,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d203560fe08eaf74321cbbd1ec8da3875dbec5b712ad90ca52d69faed6cf965 +size 23582 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_0,NEXUS_5,1.0,de].png deleted file mode 100644 index 0a0bcdc725..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_0,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fceb004153e45a443c2c3757e40e9743b0036f6a5fbd859d5b2ae9c1c3ba8903 -size 73614 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_1,NEXUS_5,1.0,de].png deleted file mode 100644 index de891bf928..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_1,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a831a3d420e4915afb0491d970080546e64c377bf0282d323583f600a6555503 -size 71210 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_2,NEXUS_5,1.0,de].png deleted file mode 100644 index 756033069b..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_2,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5bb0151e365ea9b716b6e5ccf6c8306d666bc356b23f290694fd1d6113482d25 -size 72598 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_3,NEXUS_5,1.0,de].png deleted file mode 100644 index 756033069b..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_3,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5bb0151e365ea9b716b6e5ccf6c8306d666bc356b23f290694fd1d6113482d25 -size 72598 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_0,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..9348b1ee75 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_0,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d6170a0b30d26402d4a3ad0b03726bd1b6516b8be11df9afdc1f0694b335e3d +size 71555 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_1,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..049e722748 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_1,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:097cb77dfb0a94e55df368d1d9048ec644e6dd3e7c82e8d214f80deb1e2fbffa +size 69111 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_2,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..798dc4d146 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_2,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3e472b79bebfdc8b8c3ba87a1f1f8fa7570fd2f782dbb3b890f50f5845140aa +size 70567 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_3,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..798dc4d146 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_3,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3e472b79bebfdc8b8c3ba87a1f1f8fa7570fd2f782dbb3b890f50f5845140aa +size 70567 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_4,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_4,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_4,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_0,NEXUS_5,1.0,de].png deleted file mode 100644 index 2c33e75e06..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_0,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:495fb8d17b8cae38ea7c3861014a96cff4b30200d537061b867aa9fc868c8adf -size 76560 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_1,NEXUS_5,1.0,de].png deleted file mode 100644 index 7a85cfc26a..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_1,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:75003b0a3d79c90823f2f5509faa8461c51d00e740d787c26621d3125b14e88f -size 73120 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_2,NEXUS_5,1.0,de].png deleted file mode 100644 index 756033069b..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_2,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5bb0151e365ea9b716b6e5ccf6c8306d666bc356b23f290694fd1d6113482d25 -size 72598 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_3,NEXUS_5,1.0,de].png deleted file mode 100644 index 756033069b..0000000000 --- a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_3,NEXUS_5,1.0,de].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5bb0151e365ea9b716b6e5ccf6c8306d666bc356b23f290694fd1d6113482d25 -size 72598 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_0,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..80f7d4f7b0 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_0,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1bee775c1a68bd219ce0b64556d6ce2b03f62daff98c11e4a28666387b89dbbb +size 74456 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_1,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..0a5aabccec --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_1,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afcc930123227d55b6151258f6fbad80e06ab0e81cad5361c58b1ab62a75e7ad +size 71030 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_2,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..798dc4d146 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_2,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3e472b79bebfdc8b8c3ba87a1f1f8fa7570fd2f782dbb3b890f50f5845140aa +size 70567 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_3,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..798dc4d146 --- /dev/null +++ b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_3,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3e472b79bebfdc8b8c3ba87a1f1f8fa7570fd2f782dbb3b890f50f5845140aa +size 70567 diff --git a/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_4,NEXUS_5,1.0,de].png similarity index 100% rename from screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_4,NEXUS_5,1.0,de].png rename to screenshots/de/ui_T_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_4,NEXUS_5,1.0,de].png diff --git a/screenshots/de/ui_T_t[f.signedout.impl_SignedOutView_null_SignedOutView-Day-0_1_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.signedout.impl_SignedOutView_null_SignedOutView-Day-0_1_null_0,NEXUS_5,1.0,de].png index 11e15a895c..f944d734f7 100644 --- a/screenshots/de/ui_T_t[f.signedout.impl_SignedOutView_null_SignedOutView-Day-0_1_null_0,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.signedout.impl_SignedOutView_null_SignedOutView-Day-0_1_null_0,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a79d019b012a7f2b18b058ed1c943c3464989d9f22c6beeb00cae42385e4e473 -size 67356 +oid sha256:c34ad23e46c7c27c9fed945397c25d607f1b3e1f9406568a2b56bda5980d7151 +size 67097 diff --git a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_0,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_0,NEXUS_5,1.0,de].png index 689b45e144..eb5862ce5e 100644 --- a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_0,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_0,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75cc1c4a706be9cd7faf01eb32a4a052fac47cf1c4895a1dce1e1e6e829dc156 -size 36294 +oid sha256:8706102331f8ed0d011bf7d1d89516ca5a09b05bddc18d4c92afba0f4e658dc0 +size 38990 diff --git a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_1,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_1,NEXUS_5,1.0,de].png index ff32bc7d30..324ac8ddd3 100644 --- a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_1,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_1,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0456bc9ec15195f7c16d46289e8fc13f19a739ba422e1ca10888a4ecc06a1632 -size 30540 +oid sha256:248c9f41e748d339c37785eb439a817d59f7e50a1d53af0017b3d9c8914ddcb3 +size 30289 diff --git a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_2,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_2,NEXUS_5,1.0,de].png index d85f60f604..4a13269d05 100644 --- a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_2,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_2,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7023f599e76cb8cf68825de152d5a60c8fbeedd6993c2cfbe57eadcbbb970642 -size 57857 +oid sha256:3272338432f9410ade7cbbb628a6e0700f7a8ea41f1d05b79857a020963c0415 +size 57579 diff --git a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_3,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_3,NEXUS_5,1.0,de].png index 230db21507..efbe83d029 100644 --- a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_3,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_3,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:821a476d4c2c78316d9bf16ef5843609a9b6ae31880cb1440fb94c081a651055 -size 59640 +oid sha256:e54146ed9fafca240488b8c60fd414aa995e9edfb6d93fb46d0c73ad05b72676 +size 59371 diff --git a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_4,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_4,NEXUS_5,1.0,de].png index abc3b326d9..76ed7fd4f3 100644 --- a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_4,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_4,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8fa22e63f524bde8bf0f9c725f5fd2fe7f9535ffdd7ee9870988af34977116ff -size 38591 +oid sha256:00e716ea8306c4721af99cf1d664827afe1de48f551d524da6d111f7f9f1dc7f +size 38638 diff --git a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_5,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_5,NEXUS_5,1.0,de].png index 591213011a..4405dc9066 100644 --- a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_5,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_5,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88ae7a0c26283298fed235e8f1e743df177660925e9a7c5ce668f52be6a4c55e -size 24420 +oid sha256:ea58c4c0f87718934216563986e577bfc64f40c187c5069bbc012be38357fc56 +size 24299 diff --git a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_6,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_6,NEXUS_5,1.0,de].png index 0c6ed24723..491daa044c 100644 --- a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_6,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_6,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35b2b295cf16494a9f84cb27d172db25295e4c924f55d5d33642db4914ff12a5 -size 39248 +oid sha256:2d3356ff3e7ff4368055720e1fcf0a2db6adb3cf42f1ae3952eb41f84a42245b +size 39001 diff --git a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_7,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_7,NEXUS_5,1.0,de].png index 689b45e144..b02361bfa4 100644 --- a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_7,NEXUS_5,1.0,de].png +++ b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_7,NEXUS_5,1.0,de].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75cc1c4a706be9cd7faf01eb32a4a052fac47cf1c4895a1dce1e1e6e829dc156 -size 36294 +oid sha256:b636f92a618cb34ff6be2683cd62c7617c6f156bee2e7b7a8e66cf19b121485d +size 36041 diff --git a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_8,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_8,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..45a35c2ffb --- /dev/null +++ b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_8,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f3073ff908df905b614326cee277c7c507385a5dc8953d1e4d77b5f134d3941 +size 35914 diff --git a/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_9,NEXUS_5,1.0,de].png b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_9,NEXUS_5,1.0,de].png new file mode 100644 index 0000000000..52efe2e886 --- /dev/null +++ b/screenshots/de/ui_T_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_9,NEXUS_5,1.0,de].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0704da7b8c59869c80956fc08bbde4855103080e57163fad835b4c2572e058e6 +size 23993 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index f388d4bad6..6918a023ca 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,34 +1,35 @@ // Generated file, do not edit export const screenshots = [ ["en","en-dark","de",], -["ui_S_t[f.preferences.impl.about_AboutView_null_AboutView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.about_AboutView_null_AboutView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.preferences.impl.about_AboutView_null_AboutView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.about_AboutView_null_AboutView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.login.impl.accountprovider_AccountProviderView_null_AccountProviderView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.accountprovider_AccountProviderView_null_AccountProviderView-Night-0_2_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.login.impl.accountprovider_AccountProviderView_null_AccountProviderView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.accountprovider_AccountProviderView_null_AccountProviderView-Night-0_2_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.login.impl.accountprovider_AccountProviderView_null_AccountProviderView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.accountprovider_AccountProviderView_null_AccountProviderView-Night-0_2_null_2,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.login.impl.accountprovider_AccountProviderView_null_AccountProviderView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.accountprovider_AccountProviderView_null_AccountProviderView-Night-0_2_null_3,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.login.impl.accountprovider_AccountProviderView_null_AccountProviderView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.accountprovider_AccountProviderView_null_AccountProviderView-Night-0_2_null_4,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Night-1_3_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Night-1_3_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Night-1_3_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Night-1_3_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Night-1_3_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.analytics.impl_AnalyticsOptInView_null_AnalyticsOptInView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.analytics.impl_AnalyticsOptInView_null_AnalyticsOptInView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.analytics.api.preferences_AnalyticsPreferencesView_null_AnalyticsPreferencesView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.analytics.api.preferences_AnalyticsPreferencesView_null_AnalyticsPreferencesView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.analytics_AnalyticsSettingsView_null_AnalyticsSettingsView-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.analytics_AnalyticsSettingsView_null_AnalyticsSettingsView-Night-2_4_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[services.apperror.impl_AppErrorView_null_AppErrorView-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[services.apperror.impl_AppErrorView_null_AppErrorView-Night-0_2_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.addpeople_AddPeopleView_null_AddPeopleView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Night-1_3_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Night-1_3_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Night-1_3_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Night-1_3_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.advanced_AdvancedSettingsView_null_AdvancedSettingsView-Night-1_3_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.analytics.impl_AnalyticsOptInView_null_AnalyticsOptInView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.analytics.impl_AnalyticsOptInView_null_AnalyticsOptInView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.analytics.api.preferences_AnalyticsPreferencesView_null_AnalyticsPreferencesView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.analytics.api.preferences_AnalyticsPreferencesView_null_AnalyticsPreferencesView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.analytics_AnalyticsSettingsView_null_AnalyticsSettingsView-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.analytics_AnalyticsSettingsView_null_AnalyticsSettingsView-Night-2_4_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[services.apperror.impl_AppErrorView_null_AppErrorView-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[services.apperror.impl_AppErrorView_null_AppErrorView-Night-0_2_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Day_0_null_0,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Night_1_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Day_0_null_1,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Night_1_null_1,NEXUS_5,1.0,en]",1,], +["ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Day_0_null_1,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Night_1_null_1,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Day_0_null_2,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Night_1_null_2,NEXUS_5,1.0,en]",0,], -["ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Day_0_null_3,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Night_1_null_3,NEXUS_5,1.0,en]",1,], +["ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Day_0_null_3,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Night_1_null_3,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Day_0_null_4,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncActionView_null_AsyncActionView-Night_1_null_4,NEXUS_5,1.0,en]",0,], -["ui_S_t[l.designsystem.components.async_AsyncFailure_null_AsyncFailure-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncFailure_null_AsyncFailure-Night_1_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[l.designsystem.components.async_AsyncFailure_null_AsyncFailure-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncFailure_null_AsyncFailure-Night_1_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components.async_AsyncIndicatorView_Failed__null_AsyncIndicatorView_Failed_-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncIndicatorView_Failed__null_AsyncIndicatorView_Failed_-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.components.async_AsyncIndicatorView_Loading__null_AsyncIndicatorView_Loading_-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncIndicatorView_Loading__null_AsyncIndicatorView_Loading_-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.components.async_AsyncLoading_null_AsyncLoading-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.async_AsyncLoading_null_AsyncLoading-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.messagecomposer_AttachmentSourcePickerMenu_null_AttachmentSourcePickerMenu-Day-4_4_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.messagecomposer_AttachmentSourcePickerMenu_null_AttachmentSourcePickerMenu-Night-4_5_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.messagecomposer_AttachmentSourcePickerMenu_null_AttachmentSourcePickerMenu-Day-4_4_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.messagecomposer_AttachmentSourcePickerMenu_null_AttachmentSourcePickerMenu-Night-4_5_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Night-0_2_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Night-0_2_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Night-0_2_null_2,NEXUS_5,1.0,en]",0,], @@ -38,11 +39,11 @@ export const screenshots = [ ["ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Night-0_2_null_6,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Day-0_1_null_7,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Night-0_2_null_7,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Day-0_1_null_8,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_AttachmentThumbnail_null_AttachmentThumbnail-Night-0_2_null_8,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.attachments.preview_AttachmentsPreviewView_null_AttachmentsPreviewView_0_null_0,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.messages.impl.attachments.preview_AttachmentsPreviewView_null_AttachmentsPreviewView_0_null_1,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.messages.impl.attachments.preview_AttachmentsPreviewView_null_AttachmentsPreviewView_0_null_2,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.messages.impl.attachments.preview_AttachmentsPreviewView_null_AttachmentsPreviewView_0_null_3,NEXUS_5,1.0,en]","",1,], -["ui_S_t[l.matrix.ui.components_AvatarActionBottomSheet_null_AvatarActionBottomSheet-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_AvatarActionBottomSheet_null_AvatarActionBottomSheet-Night-1_3_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.attachments.preview_AttachmentsPreviewView_null_AttachmentsPreviewView_0_null_0,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.messages.impl.attachments.preview_AttachmentsPreviewView_null_AttachmentsPreviewView_0_null_1,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.messages.impl.attachments.preview_AttachmentsPreviewView_null_AttachmentsPreviewView_0_null_2,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.messages.impl.attachments.preview_AttachmentsPreviewView_null_AttachmentsPreviewView_0_null_3,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[l.matrix.ui.components_AvatarActionBottomSheet_null_AvatarActionBottomSheet-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_AvatarActionBottomSheet_null_AvatarActionBottomSheet-Night-1_3_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en]","",0,], @@ -109,12 +110,12 @@ export const screenshots = [ ["ui_S_t[l.designsystem.components.button_BackButton_null_Buttons_BackButton_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components_BigCheckmark_null_BigCheckmark-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_BigCheckmark_null_BigCheckmark-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.components_BigIcon_null_BigIcon-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_BigIcon_null_BigIcon-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_3,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_4,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_5,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_5,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_3,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_4,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Day-3_4_null_5,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.blockedusers_BlockedUsersView_null_BlockedUsersView-Night-3_5_null_5,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components_BloomInitials_null_Bloom_BloomInitials_0_null_0,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components_BloomInitials_null_Bloom_BloomInitials_0_null_1,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components_BloomInitials_null_Bloom_BloomInitials_0_null_2,NEXUS_5,1.0,en]","",0,], @@ -125,36 +126,36 @@ export const screenshots = [ ["ui_S_t[l.designsystem.components_BloomInitials_null_Bloom_BloomInitials_0_null_7,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components_Bloom_null_Bloom_Bloom_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_BottomSheetDragHandle_null_BottomSheetDragHandle-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.theme.components_BottomSheetDragHandle_null_BottomSheetDragHandle-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.impl.bugreport_BugReportView_null_BugReportView-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.atomic.molecules_ButtonColumnMolecule_null_ButtonColumnMolecule-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.molecules_ButtonColumnMolecule_null_ButtonColumnMolecule-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.atomic.molecules_ButtonRowMolecule_null_ButtonRowMolecule-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.molecules_ButtonRowMolecule_null_ButtonRowMolecule-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.call.ui_CallScreenView_null_CallScreenView-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[f.call.ui_CallScreenView_null_CallScreenView-Night-0_2_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_null_ChangeAccountProviderView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_null_ChangeAccountProviderView-Night-4_6_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_10,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_10,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_8,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_8,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_9,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_9,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-10_12_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-10_12_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-10_12_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-10_12_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-10_12_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-10_12_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-10_11_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-10_12_null_6,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_null_ChangeAccountProviderView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_null_ChangeAccountProviderView-Night-4_6_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_10,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_10,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_8,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_8,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Day-9_10_null_9,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_null_ChangeRolesView-Night-9_11_null_9,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-11_13_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-11_13_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-11_13_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-11_13_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-11_13_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-11_13_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Day-11_12_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_null_ChangeRoomPermissionsView-Night-11_13_null_6,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.login.impl.changeserver_ChangeServerView_null_ChangeServerView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.changeserver_ChangeServerView_null_ChangeServerView-Night-1_3_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.matrix.ui.components_CheckableResolvedUserRow_null_CheckableResolvedUserRow_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[l.matrix.ui.components_CheckableUnresolvedUserRow_null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en]","",1,], +["ui_S_t[l.matrix.ui.components_CheckableUnresolvedUserRow_null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en]","",19828,], ["ui_S_t[l.designsystem.theme.components_Checkboxes_null_Toggles_Checkboxes_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_CircularProgressIndicator_null_ProgressIndicators_CircularProgressIndicator_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components_ClickableLinkText_null_Text_ClickableLinkText_0_null,NEXUS_5,1.0,en]","",0,], @@ -172,40 +173,42 @@ export const screenshots = [ ["ui_S_t[Typo_Compound_M3 Title Large,NEXUS_5,1.0,en]","",0,], ["ui_S_t[Typo_Compound_M3 Title Medium,NEXUS_5,1.0,en]","",0,], ["ui_S_t[Typo_Compound_M3 Title Small,NEXUS_5,1.0,en]","",0,], -["ui_S_t[f.createroom.impl.configureroom_ConfigureRoomView_null_ConfigureRoomView-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.configureroom_ConfigureRoomView_null_ConfigureRoomView-Night-3_5_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.createroom.impl.configureroom_ConfigureRoomView_null_ConfigureRoomView-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.configureroom_ConfigureRoomView_null_ConfigureRoomView-Night-3_5_null_1,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.createroom.impl.configureroom_ConfigureRoomView_null_ConfigureRoomView-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.configureroom_ConfigureRoomView_null_ConfigureRoomView-Night-3_5_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.configureroom_ConfigureRoomView_null_ConfigureRoomView-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.configureroom_ConfigureRoomView_null_ConfigureRoomView-Night-3_5_null_1,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.preferences.impl.developer.tracing_ConfigureTracingView_null_ConfigureTracingView-Day-5_6_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.developer.tracing_ConfigureTracingView_null_ConfigureTracingView-Night-5_7_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_null_ConfirmAccountProviderView-Day-5_6_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_null_ConfirmAccountProviderView-Night-5_7_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl.components_ConfirmRecoveryKeyBanner_null_ConfirmRecoveryKeyBanner-Day-4_5_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_ConfirmRecoveryKeyBanner_null_ConfirmRecoveryKeyBanner-Night-4_6_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_null_ConfirmAccountProviderView-Day-5_6_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_null_ConfirmAccountProviderView-Night-5_7_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl.components_ConfirmRecoveryKeyBanner_null_ConfirmRecoveryKeyBanner-Day-4_5_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_ConfirmRecoveryKeyBanner_null_ConfirmRecoveryKeyBanner-Night-4_6_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components.dialogs_ConfirmationDialogContent_null_Dialogs_ConfirmationDialogContent_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.dialogs_ConfirmationDialog_null_ConfirmationDialog-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.dialogs_ConfirmationDialog_null_ConfirmationDialog-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.networkmonitor.api.ui_ConnectivityIndicatorView_null_ConnectivityIndicatorView-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[f.networkmonitor.api.ui_ConnectivityIndicatorView_null_ConnectivityIndicatorView-Night-0_2_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.rageshake.api.crash_CrashDetectionView_null_CrashDetectionView-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.api.crash_CrashDetectionView_null_CrashDetectionView-Night-0_2_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_7,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Night-4_6_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_1,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Night-4_6_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_2,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Night-4_6_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.designsystem.theme.components.previews_DatePickerDark_null_DateTimepickers_DatePickerDark_0_null,NEXUS_5,1.0,en]","",1,], -["ui_S_t[l.designsystem.theme.components.previews_DatePickerLight_null_DateTimepickers_DatePickerLight_0_null,NEXUS_5,1.0,en]","",1,], +["ui_S_t[f.rageshake.api.crash_CrashDetectionView_null_CrashDetectionView-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.api.crash_CrashDetectionView_null_CrashDetectionView-Night-0_2_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.createkey_CreateNewRecoveryKeyView_null_CreateNewRecoveryKeyView-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.createkey_CreateNewRecoveryKeyView_null_CreateNewRecoveryKeyView-Night-0_2_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Day-0_1_null_7,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.create_CreatePollView_null_CreatePollView-Night-0_2_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Night-4_6_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_1,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Night-4_6_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_2,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Night-4_6_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Day-4_5_null_3,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.root_CreateRoomRootView_null_CreateRoomRootView-Night-4_6_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.designsystem.theme.components.previews_DatePickerDark_null_DateTimepickers_DatePickerDark_0_null,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[l.designsystem.theme.components.previews_DatePickerLight_null_DateTimepickers_DatePickerLight_0_null,NEXUS_5,1.0,en]","",19828,], ["ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Night-1_3_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Night-1_3_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Night-1_3_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Night-1_3_null_3,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Night-1_3_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Night-1_3_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Night-1_3_null_3,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl.direct_DefaultDirectLogoutView_null_DefaultDirectLogoutView-Night-1_3_null_4,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.preferences.impl.notifications.edit_DefaultNotificationSettingOption_null_DefaultNotificationSettingOption-Day-7_8_null,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_DefaultNotificationSettingOption_null_DefaultNotificationSettingOption-Night-7_9_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Day-7_8_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Night-7_9_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Day-6_7_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Night-6_8_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Night-4_6_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Day-4_5_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Night-4_6_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Day-4_5_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Night-4_6_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.designsystem.atomic.molecules_DialogLikeBannerMolecule_null_DialogLikeBannerMolecule-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.molecules_DialogLikeBannerMolecule_null_DialogLikeBannerMolecule-Night_1_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.preferences.impl.notifications.edit_DefaultNotificationSettingOption_null_DefaultNotificationSettingOption-Day-7_8_null,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_DefaultNotificationSettingOption_null_DefaultNotificationSettingOption-Night-7_9_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Day-7_8_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Night-7_9_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Day-6_7_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Night-6_8_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Night-4_6_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Day-4_5_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Night-4_6_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Day-4_5_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.developer_DeveloperSettingsView_null_DeveloperSettingsView-Night-4_6_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.designsystem.atomic.molecules_DialogLikeBannerMolecule_null_DialogLikeBannerMolecule-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.molecules_DialogLikeBannerMolecule_null_DialogLikeBannerMolecule-Night_1_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.theme.components_DialogWithDestructiveButton_null_Dialogs_Dialogwithdestructivebutton_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_DialogWithOnlyMessageAndOkButton_null_Dialogs_Dialogwithonlymessageandokbutton_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_DialogWithThirdButton_null_Dialogs_Dialogwiththirdbutton_0_null,NEXUS_5,1.0,en]","",0,], @@ -216,21 +219,21 @@ export const screenshots = [ ["ui_S_t[l.designsystem.text_DpScale_1_0f__null_DpScale_1_0f__0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.text_DpScale_1_5f__null_DpScale_1_5f__0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_DropdownMenuItem_null_Menus_DropdownMenuItem_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Day-8_9_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Night-8_10_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Day-8_9_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Night-8_10_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Day-8_9_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Night-8_10_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Day-8_9_null_3,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Night-8_10_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Day-8_9_null_4,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Night-8_10_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.user.editprofile_EditUserProfileView_null_EditUserProfileView-Day-10_11_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.user.editprofile_EditUserProfileView_null_EditUserProfileView-Night-10_12_null_0,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Day-8_9_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Night-8_10_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Day-8_9_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Night-8_10_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Day-8_9_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Night-8_10_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Day-8_9_null_3,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Night-8_10_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Day-8_9_null_4,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_null_EditDefaultNotificationSettingView-Night-8_10_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.user.editprofile_EditUserProfileView_null_EditUserProfileView-Day-10_11_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.user.editprofile_EditUserProfileView_null_EditUserProfileView-Night-10_12_null_0,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.atomic.atoms_ElementLogoAtomLargeNoBlurShadow_null_ElementLogoAtomLargeNoBlurShadow-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.atoms_ElementLogoAtomLargeNoBlurShadow_null_ElementLogoAtomLargeNoBlurShadow-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.atomic.atoms_ElementLogoAtomLarge_null_ElementLogoAtomLarge-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.atoms_ElementLogoAtomLarge_null_ElementLogoAtomLarge-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_null_ElementLogoAtomMediumNoBlurShadow-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_null_ElementLogoAtomMediumNoBlurShadow-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.atomic.atoms_ElementLogoAtomMedium_null_ElementLogoAtomMedium-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.atoms_ElementLogoAtomMedium_null_ElementLogoAtomMedium-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiItem_null_EmojiItem-Day-31_31_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiItem_null_EmojiItem-Night-31_32_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiPicker_null_EmojiPicker-Day-32_32_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiPicker_null_EmojiPicker-Night-32_33_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-57_57_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-57_58_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.designsystem.components.dialogs_ErrorDialogContent_null_Dialogs_ErrorDialogContent_0_null,NEXUS_5,1.0,en]","",1,], -["ui_S_t[l.designsystem.components.dialogs_ErrorDialog_null_ErrorDialog-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.dialogs_ErrorDialog_null_ErrorDialog-Night_1_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-57_57_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-57_58_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.designsystem.components.dialogs_ErrorDialogContent_null_Dialogs_ErrorDialogContent_0_null,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[l.designsystem.components.dialogs_ErrorDialog_null_ErrorDialog-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.dialogs_ErrorDialog_null_ErrorDialog-Night_1_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.debug_EventDebugInfoView_null_EventDebugInfoView-Day-62_62_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.debug_EventDebugInfoView_null_EventDebugInfoView-Night-62_63_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.theme.components_FilledButtonLarge_null_Buttons_FilledButtonLarge_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_FilledButtonMedium_null_Buttons_FilledButtonMedium_0_null,NEXUS_5,1.0,en]","",0,], @@ -240,7 +243,7 @@ export const screenshots = [ ["ui_S_t[f.messages.impl.forward_ForwardMessagesView_null_ForwardMessagesView-Day-2_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.forward_ForwardMessagesView_null_ForwardMessagesView-Night-2_3_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.forward_ForwardMessagesView_null_ForwardMessagesView-Day-2_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.forward_ForwardMessagesView_null_ForwardMessagesView-Night-2_3_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.forward_ForwardMessagesView_null_ForwardMessagesView-Day-2_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.forward_ForwardMessagesView_null_ForwardMessagesView-Night-2_3_null_2,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.forward_ForwardMessagesView_null_ForwardMessagesView-Day-2_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.forward_ForwardMessagesView_null_ForwardMessagesView-Night-2_3_null_3,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.forward_ForwardMessagesView_null_ForwardMessagesView-Day-2_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.forward_ForwardMessagesView_null_ForwardMessagesView-Night-2_3_null_3,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Day-52_52_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Night-52_53_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.atomic.pages_HeaderFooterPage_null_HeaderFooterPage-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.pages_HeaderFooterPage_null_HeaderFooterPage-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.theme.components_HorizontalDivider_null_Dividers_HorizontalDivider_0_null,NEXUS_5,1.0,en]","",0,], @@ -259,29 +262,30 @@ export const screenshots = [ ["ui_S_t[l.designsystem.icons_IconsOther_null_IconsOther-Day_0_null_0,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.icons_IconsOther_null_IconsOther-Night_1_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.atomic.molecules_InfoListItemMolecule_null_InfoListItemMolecule-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.molecules_InfoListItemMolecule_null_InfoListItemMolecule-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.atomic.organisms_InfoListOrganism_null_InfoListOrganism-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.organisms_InfoListOrganism_null_InfoListOrganism-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl_InviteListView_null_InviteListView-Night-0_2_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.invitelist.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-1_3_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl_InvitesEntryPointView_null_InvitesEntryPointView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_InvitesEntryPointView_null_InvitesEntryPointView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl_InvitesEntryPointView_null_InvitesEntryPointView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_InvitesEntryPointView_null_InvitesEntryPointView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_5,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Day-1_2_null_6,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.invitelist_InviteListView_null_InviteListView-Night-1_3_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.invite.impl.components_InviteSummaryRow_null_InviteSummaryRow-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl_InvitesEntryPointView_null_InvitesEntryPointView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_InvitesEntryPointView_null_InvitesEntryPointView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl_InvitesEntryPointView_null_InvitesEntryPointView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_InvitesEntryPointView_null_InvitesEntryPointView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components_LabelledCheckbox_null_Toggles_LabelledCheckbox_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components_LabelledOutlinedTextField_null_LabelledOutlinedTextField-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_LabelledOutlinedTextField_null_LabelledOutlinedTextField-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.components_LabelledTextField_null_LabelledTextField-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_LabelledTextField_null_LabelledTextField-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_6,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.leaveroom.api_LeaveRoomView_null_LeaveRoomView-Night-0_2_null_6,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.theme.components_LinearProgressIndicator_null_ProgressIndicators_LinearProgressIndicator_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.dialogs_ListDialogContent_null_Dialogs_ListDialogContent_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.dialogs_ListDialog_null_ListDialog-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.dialogs_ListDialog_null_ListDialog-Night_1_null,NEXUS_5,1.0,en]",0,], @@ -330,26 +334,26 @@ export const screenshots = [ ["ui_S_t[l.designsystem.theme.components_ListSupportingTextNoPadding_null_Listsections_Listsupportingtext-nopadding_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_ListSupportingTextSmallPadding_null_Listsections_Listsupportingtext-smallpadding_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.textcomposer.components_LiveWaveformView_null_LiveWaveformView-Day-11_12_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer.components_LiveWaveformView_null_LiveWaveformView-Night-11_13_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_0,NEXUS_5,1.0,en]","ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,en]","ui_S_t[appnav.room_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Night-1_3_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Night-1_3_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Night-1_3_null_2,NEXUS_5,1.0,en]",1,], +["ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_0,NEXUS_5,1.0,en]","ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_0,NEXUS_5,1.0,en]",0,], +["ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Day-2_2_null_1,NEXUS_5,1.0,en]","ui_S_t[appnav.room.joined_LoadingRoomNodeView_null_LoadingRoomNodeView-Night-2_3_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Night-1_3_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Night-1_3_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.settings_LockScreenSettingsView_null_LockScreenSettingsView-Night-1_3_null_2,NEXUS_5,1.0,en]",19828,], ["ui_S_t[appnav.loggedin_LoggedInView_null_LoggedInView-Day-0_0_null_0,NEXUS_5,1.0,en]","ui_S_t[appnav.loggedin_LoggedInView_null_LoggedInView-Night-0_1_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[appnav.loggedin_LoggedInView_null_LoggedInView-Day-0_0_null_1,NEXUS_5,1.0,en]","ui_S_t[appnav.loggedin_LoggedInView_null_LoggedInView-Night-0_1_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Day-6_7_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Night-6_8_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Day-6_7_null_1,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Night-6_8_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Day-6_7_null_2,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Night-6_8_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_7,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_8,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_8,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_9,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_9,NEXUS_5,1.0,en]",1,], +["ui_S_t[appnav.loggedin_LoggedInView_null_LoggedInView-Day-0_0_null_1,NEXUS_5,1.0,en]","ui_S_t[appnav.loggedin_LoggedInView_null_LoggedInView-Night-0_1_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Day-6_7_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Night-6_8_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Day-6_7_null_1,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Night-6_8_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Day-6_7_null_2,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.loginpassword_LoginPasswordView_null_LoginPasswordView-Night-6_8_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_7,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_8,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_8,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Day-0_1_null_9,NEXUS_5,1.0,en]","ui_S_t[f.logout.impl_LogoutView_null_LogoutView-Night-0_2_null_9,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components.button_MainActionButton_null_Buttons_MainActionButton_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.matrix.ui.components_MatrixUserHeaderPlaceholder_null_MatrixUserHeaderPlaceholder-Day-3_4_null,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_MatrixUserHeaderPlaceholder_null_MatrixUserHeaderPlaceholder-Night-3_5_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.matrix.ui.components_MatrixUserHeader_null_MatrixUserHeader-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_MatrixUserHeader_null_MatrixUserHeader-Night-2_4_null_0,NEXUS_5,1.0,en]",0,], @@ -359,7 +363,7 @@ export const screenshots = [ ["ui_S_t[l.mediaviewer.api.viewer_MediaViewerView_null_MediaViewerView_0_null_0,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.mediaviewer.api.viewer_MediaViewerView_null_MediaViewerView_0_null_1,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.mediaviewer.api.viewer_MediaViewerView_null_MediaViewerView_0_null_10,NEXUS_5,1.0,en]","",0,], -["ui_S_t[l.mediaviewer.api.viewer_MediaViewerView_null_MediaViewerView_0_null_2,NEXUS_5,1.0,en]","",1,], +["ui_S_t[l.mediaviewer.api.viewer_MediaViewerView_null_MediaViewerView_0_null_2,NEXUS_5,1.0,en]","",19828,], ["ui_S_t[l.mediaviewer.api.viewer_MediaViewerView_null_MediaViewerView_0_null_3,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.mediaviewer.api.viewer_MediaViewerView_null_MediaViewerView_0_null_4,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.mediaviewer.api.viewer_MediaViewerView_null_MediaViewerView_0_null_5,NEXUS_5,1.0,en]","",0,], @@ -369,10 +373,10 @@ export const screenshots = [ ["ui_S_t[l.mediaviewer.api.viewer_MediaViewerView_null_MediaViewerView_0_null_9,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_MediumTopAppBar_null_AppBars_MediumTopAppBar_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.textcomposer.mentions_MentionSpan_null_MentionSpan-Day-18_19_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer.mentions_MentionSpan_null_MentionSpan-Night-18_20_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.mentions_MentionSuggestionsPickerView__null_MentionSuggestionsPickerView_-Day-3_3_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.mentions_MentionSuggestionsPickerView__null_MentionSuggestionsPickerView_-Night-3_4_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.mentions_MentionSuggestionsPickerView__null_MentionSuggestionsPickerView_-Day-3_3_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.mentions_MentionSuggestionsPickerView__null_MentionSuggestionsPickerView_-Night-3_4_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.theme.components.previews_Menu_null_Menus_Menu_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[f.messages.impl.messagecomposer_MessageComposerViewVoice_null_MessageComposerViewVoice-Day-6_6_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.messagecomposer_MessageComposerViewVoice_null_MessageComposerViewVoice-Night-6_7_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.messagecomposer_MessageComposerView_null_MessageComposerView-Day-5_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.messagecomposer_MessageComposerView_null_MessageComposerView-Night-5_6_null_0,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.messagecomposer_MessageComposerView_null_MessageComposerView-Day-5_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.messagecomposer_MessageComposerView_null_MessageComposerView-Night-5_6_null_0,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components_MessageEventBubble_null_MessageEventBubble-Day-9_9_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_MessageEventBubble_null_MessageEventBubble-Night-9_10_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_MessageEventBubble_null_MessageEventBubble-Day-9_9_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_MessageEventBubble_null_MessageEventBubble-Night-9_10_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_MessageEventBubble_null_MessageEventBubble-Day-9_9_null_10,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_MessageEventBubble_null_MessageEventBubble-Night-9_10_null_10,NEXUS_5,1.0,en]",0,], @@ -396,23 +400,23 @@ export const screenshots = [ ["ui_S_t[f.messages.impl.timeline.components_MessagesReactionButton_null_MessagesReactionButton-Day-11_11_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_MessagesReactionButton_null_MessagesReactionButton-Night-11_12_null_2,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_MessagesReactionButton_null_MessagesReactionButton-Day-11_11_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_MessagesReactionButton_null_MessagesReactionButton-Night-11_12_null_3,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_MessagesReactionExtraButtons_null_MessagesReactionExtraButtons-Day-13_13_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_MessagesReactionExtraButtons_null_MessagesReactionExtraButtons-Night-13_14_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.typing_MessagesViewWithTyping_null_MessagesViewWithTyping-Day-63_63_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_MessagesViewWithTyping_null_MessagesViewWithTyping-Night-63_64_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.typing_MessagesViewWithTyping_null_MessagesViewWithTyping-Day-63_63_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_MessagesViewWithTyping_null_MessagesViewWithTyping-Night-63_64_null_1,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.typing_MessagesViewWithTyping_null_MessagesViewWithTyping-Day-63_63_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_MessagesViewWithTyping_null_MessagesViewWithTyping-Night-63_64_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.typing_MessagesViewWithTyping_null_MessagesViewWithTyping-Day-63_63_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_MessagesViewWithTyping_null_MessagesViewWithTyping-Night-63_64_null_1,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.typing_MessagesViewWithTyping_null_MessagesViewWithTyping-Day-63_63_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_MessagesViewWithTyping_null_MessagesViewWithTyping-Night-63_64_null_2,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_0,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_0,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_1,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_10,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_10,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_11,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_11,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_12,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_12,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_6,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_7,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_8,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_8,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_9,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_9,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Day-11_12_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Night-11_13_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_10,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_10,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_11,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_11,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_12,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_12,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_6,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_7,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_8,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_8,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Day-0_0_null_9,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl_MessagesView_null_MessagesView-Night-0_1_null_9,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Day-11_12_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Night-11_13_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.theme.components_ModalBottomSheetDark_null_BottomSheets_ModalBottomSheetDark_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_ModalBottomSheetLayoutDark_null_BottomSheets_ModalBottomSheetLayoutDark_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_ModalBottomSheetLayoutLight_null_BottomSheets_ModalBottomSheetLayoutLight_0_null,NEXUS_5,1.0,en]","",0,], @@ -422,64 +426,66 @@ export const screenshots = [ ["ui_S_t[l.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_null_Listitems_MultipleselectionListitem-selectionintrailingcontent_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.list_MutipleSelectionListItemSelected_null_Listitems_MultipleselectionListitem-selectioninsupportingtext_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.list_MutipleSelectionListItem_null_Listitems_MultipleselectionListitem-noselection_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-6_7_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-6_8_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-6_7_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-6_8_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-6_7_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-6_8_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-6_7_null_3,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-6_8_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-6_7_null_4,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-6_8_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-6_7_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-6_8_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-6_7_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-6_8_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-6_7_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-6_8_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-6_7_null_3,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-6_8_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-6_7_null_4,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-6_8_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.ftue.impl.notifications_NotificationsOptInView_null_NotificationsOptInView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.login.impl.oidc.webview_OidcView_null_OidcView-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.oidc.webview_OidcView_null_OidcView-Night-3_5_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.login.impl.oidc.webview_OidcView_null_OidcView-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.oidc.webview_OidcView_null_OidcView-Night-3_5_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.atomic.pages_OnBoardingPage_null_OnBoardingPage-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.pages_OnBoardingPage_null_OnBoardingPage-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.onboarding.impl_OnBoardingScreen_null_OnBoardingScreen-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.theme.components_OutlinedButtonLarge_null_Buttons_OutlinedButtonLarge_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_OutlinedButtonMedium_null_Buttons_OutlinedButtonMedium_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_OutlinedTextFieldsDark_null_TextFields_OutlinedTextFieldsDark_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_OutlinedTextFields_null_TextFields_OutlinedTextFields_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_null_PendingMemberRowWithLongName-Day-10_11_null,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_null_PendingMemberRowWithLongName-Night-10_12_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[l.permissions.api_PermissionsView_null_PermissionsView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.lockscreen.impl.components_PinEntryTextField_null_PinEntryTextField-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.components_PinEntryTextField_null_PinEntryTextField-Night-0_2_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.components_PinIcon_null_PinIcon-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_PinIcon_null_PinIcon-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.lockscreen.impl.unlock.keypad_PinKeypad_null_PinKeypad-Day-6_7_null,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock.keypad_PinKeypad_null_PinKeypad-Night-6_8_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_0,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_1,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_2,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_3,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_4,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_5,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_6,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_1,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_2,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_3,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_4,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_5,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_6,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_6,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_0,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_1,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_2,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_3,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_4,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_5,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Day-5_6_null_6,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockDefaultView_null_PinUnlockDefaultView-Night-5_7_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_1,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_2,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_3,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_4,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_5,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Day-4_5_null_6,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.unlock_PinUnlockInAppView_null_PinUnlockInAppView-Night-4_6_null_6,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.atomic.atoms_PlaceholderAtom_null_PlaceholderAtom-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.atoms_PlaceholderAtom_null_PlaceholderAtom-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.poll.api.pollcontent_PollAnswerDisclosedNotSelected_null_PollAnswerDisclosedNotSelected-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerDisclosedNotSelected_null_PollAnswerDisclosedNotSelected-Night-0_2_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.api.pollcontent_PollAnswerDisclosedSelected_null_PollAnswerDisclosedSelected-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerDisclosedSelected_null_PollAnswerDisclosedSelected-Night-1_3_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.api.pollcontent_PollAnswerEndedSelected_null_PollAnswerEndedSelected-Day-6_7_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerEndedSelected_null_PollAnswerEndedSelected-Night-6_8_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.api.pollcontent_PollAnswerEndedWinnerNotSelected_null_PollAnswerEndedWinnerNotSelected-Day-4_5_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerEndedWinnerNotSelected_null_PollAnswerEndedWinnerNotSelected-Night-4_6_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.api.pollcontent_PollAnswerEndedWinnerSelected_null_PollAnswerEndedWinnerSelected-Day-5_6_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerEndedWinnerSelected_null_PollAnswerEndedWinnerSelected-Night-5_7_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.poll.api.pollcontent_PollAnswerDisclosedNotSelected_null_PollAnswerDisclosedNotSelected-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerDisclosedNotSelected_null_PollAnswerDisclosedNotSelected-Night-0_2_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.api.pollcontent_PollAnswerDisclosedSelected_null_PollAnswerDisclosedSelected-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerDisclosedSelected_null_PollAnswerDisclosedSelected-Night-1_3_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.api.pollcontent_PollAnswerEndedSelected_null_PollAnswerEndedSelected-Day-6_7_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerEndedSelected_null_PollAnswerEndedSelected-Night-6_8_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.api.pollcontent_PollAnswerEndedWinnerNotSelected_null_PollAnswerEndedWinnerNotSelected-Day-4_5_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerEndedWinnerNotSelected_null_PollAnswerEndedWinnerNotSelected-Night-4_6_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.api.pollcontent_PollAnswerEndedWinnerSelected_null_PollAnswerEndedWinnerSelected-Day-5_6_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerEndedWinnerSelected_null_PollAnswerEndedWinnerSelected-Night-5_7_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.poll.api.pollcontent_PollAnswerUndisclosedNotSelected_null_PollAnswerUndisclosedNotSelected-Day-2_3_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerUndisclosedNotSelected_null_PollAnswerUndisclosedNotSelected-Night-2_4_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.poll.api.pollcontent_PollAnswerUndisclosedSelected_null_PollAnswerUndisclosedSelected-Day-3_4_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollAnswerUndisclosedSelected_null_PollAnswerUndisclosedSelected-Night-3_5_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.poll.api.pollcontent_PollContentCreatorEditable_null_PollContentCreatorEditable-Day-10_11_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentCreatorEditable_null_PollContentCreatorEditable-Night-10_12_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.api.pollcontent_PollContentCreatorEnded_null_PollContentCreatorEnded-Day-12_13_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentCreatorEnded_null_PollContentCreatorEnded-Night-12_14_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.api.pollcontent_PollContentCreator_null_PollContentCreator-Day-11_12_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentCreator_null_PollContentCreator-Night-11_13_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.api.pollcontent_PollContentDisclosed_null_PollContentDisclosed-Day-8_9_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentDisclosed_null_PollContentDisclosed-Night-8_10_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.api.pollcontent_PollContentEnded_null_PollContentEnded-Day-9_10_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentEnded_null_PollContentEnded-Night-9_11_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.api.pollcontent_PollContentUndisclosed_null_PollContentUndisclosed-Day-7_8_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentUndisclosed_null_PollContentUndisclosed-Night-7_9_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Night-1_3_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Night-1_3_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Night-1_3_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Night-1_3_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Night-1_3_null_4,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.poll.api.pollcontent_PollContentCreatorEditable_null_PollContentCreatorEditable-Day-10_11_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentCreatorEditable_null_PollContentCreatorEditable-Night-10_12_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.api.pollcontent_PollContentCreatorEnded_null_PollContentCreatorEnded-Day-12_13_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentCreatorEnded_null_PollContentCreatorEnded-Night-12_14_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.api.pollcontent_PollContentCreator_null_PollContentCreator-Day-11_12_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentCreator_null_PollContentCreator-Night-11_13_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.api.pollcontent_PollContentDisclosed_null_PollContentDisclosed-Day-8_9_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentDisclosed_null_PollContentDisclosed-Night-8_10_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.api.pollcontent_PollContentEnded_null_PollContentEnded-Day-9_10_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentEnded_null_PollContentEnded-Night-9_11_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.api.pollcontent_PollContentUndisclosed_null_PollContentUndisclosed-Day-7_8_null,NEXUS_5,1.0,en]","ui_S_t[f.poll.api.pollcontent_PollContentUndisclosed_null_PollContentUndisclosed-Night-7_9_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Night-1_3_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Night-1_3_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Night-1_3_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Night-1_3_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.poll.impl.history_PollHistoryView_null_PollHistoryView-Night-1_3_null_4,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components.preferences_PreferenceCategory_null_Preferences_PreferenceCategory_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.preferences_PreferenceCheckbox_null_Preferences_PreferenceCheckbox_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.preferences_PreferenceDivider_null_Preferences_PreferenceDivider_0_null,NEXUS_5,1.0,en]","",0,], @@ -495,169 +501,169 @@ export const screenshots = [ ["ui_S_t[l.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_null_Preferences_PreferenceTextWithEndBadgeDark_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_null_Preferences_PreferenceTextWithEndBadgeLight_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.preferences_PreferenceView_null_PreferenceView-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.preferences_PreferenceView_null_PreferenceView-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.preferences.impl.root_PreferencesRootViewDark_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.preferences.impl.root_PreferencesRootViewDark_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.preferences.impl.root_PreferencesRootViewLight_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.preferences.impl.root_PreferencesRootViewLight_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en]","",1,], +["ui_S_t[f.preferences.impl.root_PreferencesRootViewDark_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.preferences.impl.root_PreferencesRootViewDark_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.preferences.impl.root_PreferencesRootViewLight_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.preferences.impl.root_PreferencesRootViewLight_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en]","",19828,], ["ui_S_t[f.messages.impl.timeline.components.event_ProgressButton_null_ProgressButton-Day-51_51_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_ProgressButton_null_ProgressButton-Night-51_52_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[l.designsystem.components_ProgressDialogContent_null_Dialogs_ProgressDialogContent_0_null,NEXUS_5,1.0,en]","",1,], -["ui_S_t[l.designsystem.components_ProgressDialog_null_ProgressDialog-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_ProgressDialog_null_ProgressDialog-Night_1_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[l.designsystem.components_ProgressDialogContent_null_Dialogs_ProgressDialogContent_0_null,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[l.designsystem.components_ProgressDialog_null_ProgressDialog-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_ProgressDialog_null_ProgressDialog-Night_1_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.theme.components_RadioButton_null_Toggles_RadioButton_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[f.rageshake.api.detection_RageshakeDialogContent_null_RageshakeDialogContent-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.api.detection_RageshakeDialogContent_null_RageshakeDialogContent-Night-1_3_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.rageshake.api.preferences_RageshakePreferencesView_null_RageshakePreferencesView-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.api.preferences_RageshakePreferencesView_null_RageshakePreferencesView-Night-2_4_null_0,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.rageshake.api.detection_RageshakeDialogContent_null_RageshakeDialogContent-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.api.detection_RageshakeDialogContent_null_RageshakeDialogContent-Night-1_3_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.rageshake.api.preferences_RageshakePreferencesView_null_RageshakePreferencesView-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.api.preferences_RageshakePreferencesView_null_RageshakePreferencesView-Night-2_4_null_0,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.rageshake.api.preferences_RageshakePreferencesView_null_RageshakePreferencesView-Day-2_3_null_1,NEXUS_5,1.0,en]","ui_S_t[f.rageshake.api.preferences_RageshakePreferencesView_null_RageshakePreferencesView-Night-2_4_null_1,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_10,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_10,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_11,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_11,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_4,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_5,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_6,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_7,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_8,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_8,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-6_7_null_9,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-6_8_null_9,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-55_55_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-55_56_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_10,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_10,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_11,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_11,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_4,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_5,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_6,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_7,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_8,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_8,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Day-7_8_null_9,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup.views_RecoveryKeyView_null_RecoveryKeyView-Night-7_9_null_9,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.atomic.atoms_RedIndicatorAtom_null_RedIndicatorAtom-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.atoms_RedIndicatorAtom_null_RedIndicatorAtom-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_ReplySwipeIndicator_null_ReplySwipeIndicator-Day-14_14_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_ReplySwipeIndicator_null_ReplySwipeIndicator-Night-14_15_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.designsystem.components.dialogs_RetryDialogContent_null_Dialogs_RetryDialogContent_0_null,NEXUS_5,1.0,en]","",1,], -["ui_S_t[l.designsystem.components.dialogs_RetryDialog_null_RetryDialog-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.dialogs_RetryDialog_null_RetryDialog-Night_1_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Day-7_7_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.report_ReportMessageView_null_ReportMessageView-Night-7_8_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.designsystem.components.dialogs_RetryDialogContent_null_Dialogs_RetryDialogContent_0_null,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[l.designsystem.components.dialogs_RetryDialog_null_RetryDialog-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.dialogs_RetryDialog_null_RetryDialog-Night_1_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-56_56_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-56_57_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-56_56_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-56_57_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_9,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_0,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_1,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_2,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_3,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_4,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_5,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_6,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_7,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_8,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_9,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_7,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-56_56_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-56_57_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Day-8_9_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.rolesandpermissions_RolesAndPermissionView_null_RolesAndPermissionView-Night-8_10_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_1_null_9,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.edit_RoomDetailsEditView_null_RoomDetailsEditView-Night-0_2_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_0,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_1,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_2,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_3,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_4,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_5,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_6,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_7,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_8,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_0_null_9,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdirectory.impl.root_RoomDirectoryView_null_RoomDirectoryView-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Day-1_2_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.invite_RoomInviteMembers_null_RoomInviteMembers-Night-1_3_null_7,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-5_6_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-5_7_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-5_6_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-5_7_null_1,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-5_6_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-5_7_null_1,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-5_6_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-5_7_null_2,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-5_6_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-5_7_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-5_6_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-5_7_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl_RoomListModalBottomSheetContentForDm_null_RoomListModalBottomSheetContentForDm-Day-2_3_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListModalBottomSheetContentForDm_null_RoomListModalBottomSheetContentForDm-Night-2_4_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl_RoomListModalBottomSheetContent_null_RoomListModalBottomSheetContent-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListModalBottomSheetContent_null_RoomListModalBottomSheetContent-Night-1_3_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-5_6_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-5_7_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-5_6_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-5_7_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl_RoomListModalBottomSheetContentForDm_null_RoomListModalBottomSheetContentForDm-Day-2_3_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListModalBottomSheetContentForDm_null_RoomListModalBottomSheetContentForDm-Night-2_4_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl_RoomListModalBottomSheetContent_null_RoomListModalBottomSheetContent-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListModalBottomSheetContent_null_RoomListModalBottomSheetContent-Night-1_3_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-12_13_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-12_14_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-12_13_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-12_14_null_1,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-12_13_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-12_14_null_1,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-12_13_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-12_14_null_2,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_1,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_10,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_10,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_10,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_10,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_11,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_11,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_12,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_12,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_12,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_12,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_2,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_8,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_8,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_8,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_8,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_9,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_9,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Night-3_5_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Night-3_5_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Day-3_4_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Night-3_5_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_6,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_6,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_4,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Night-3_5_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Night-3_5_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Day-3_4_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberBannedList_null_RoomMemberBannedList-Night-3_5_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_3_null_6,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_2_null_6,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_4,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_5,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_8,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_8,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Day-2_3_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members_RoomMemberList_null_RoomMemberList-Night-2_4_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_8,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_8,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Day-4_5_null_9,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.members.moderation_RoomMembersModerationView_null_RoomMembersModerationView-Night-4_6_null_9,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.createroom.impl.components_RoomPrivacyOption_null_RoomPrivacyOption-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_RoomPrivacyOption_null_RoomPrivacyOption-Night-1_3_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.roomdetails.impl.notificationsettings_RoomPrivacyOption_null_RoomPrivacyOption-Day-5_6_null,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomPrivacyOption_null_RoomPrivacyOption-Night-5_7_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_2,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_3,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_4,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_5,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Day-6_7_null_6,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomNotificationSettings_null_RoomNotificationSettings-Night-6_8_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.components_RoomPrivacyOption_null_RoomPrivacyOption-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_RoomPrivacyOption_null_RoomPrivacyOption-Night-1_3_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.roomdetails.impl.notificationsettings_RoomPrivacyOption_null_RoomPrivacyOption-Day-5_6_null,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_RoomPrivacyOption_null_RoomPrivacyOption-Night-5_7_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[l.roomselect.impl_RoomSelectView_null_RoomSelectView-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Day-8_9_null,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Night-8_10_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_1,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_1,NEXUS_5,1.0,en]",0,], @@ -687,88 +693,88 @@ export const screenshots = [ ["ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_7,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_7,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_8,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_8,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_9,NEXUS_5,1.0,en]","ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_9,NEXUS_5,1.0,en]",0,], -["ui_S_t[appnav.root_Root_null_Root-Day-3_3_null_0,NEXUS_5,1.0,en]","ui_S_t[appnav.root_Root_null_Root-Night-3_4_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[appnav.root_Root_null_Root-Day-3_3_null_1,NEXUS_5,1.0,en]","ui_S_t[appnav.root_Root_null_Root-Night-3_4_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[appnav.root_Root_null_Root-Day-3_3_null_2,NEXUS_5,1.0,en]","ui_S_t[appnav.root_Root_null_Root-Night-3_4_null_2,NEXUS_5,1.0,en]",1,], +["ui_S_t[appnav.root_Root_null_Root-Day-3_3_null_0,NEXUS_5,1.0,en]","ui_S_t[appnav.root_Root_null_Root-Night-3_4_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[appnav.root_Root_null_Root-Day-3_3_null_1,NEXUS_5,1.0,en]","ui_S_t[appnav.root_Root_null_Root-Night-3_4_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[appnav.root_Root_null_Root-Day-3_3_null_2,NEXUS_5,1.0,en]","ui_S_t[appnav.root_Root_null_Root-Night-3_4_null_2,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.atomic.atoms_RoundedIconAtom_null_RoundedIconAtom-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.atoms_RoundedIconAtom_null_RoundedIconAtom-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.verifysession.impl.emoji_SasEmojis_null_SasEmojis-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl.emoji_SasEmojis_null_SasEmojis-Night-1_3_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.login.impl.screens.searchaccountprovider_SearchAccountProviderView_null_SearchAccountProviderView-Day-7_8_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.searchaccountprovider_SearchAccountProviderView_null_SearchAccountProviderView-Night-7_9_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.login.impl.screens.searchaccountprovider_SearchAccountProviderView_null_SearchAccountProviderView-Day-7_8_null_1,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.searchaccountprovider_SearchAccountProviderView_null_SearchAccountProviderView-Night-7_9_null_1,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.verifysession.impl.emoji_SasEmojis_null_SasEmojis-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl.emoji_SasEmojis_null_SasEmojis-Night-1_3_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.login.impl.screens.searchaccountprovider_SearchAccountProviderView_null_SearchAccountProviderView-Day-7_8_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.searchaccountprovider_SearchAccountProviderView_null_SearchAccountProviderView-Night-7_9_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.login.impl.screens.searchaccountprovider_SearchAccountProviderView_null_SearchAccountProviderView-Day-7_8_null_1,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.searchaccountprovider_SearchAccountProviderView_null_SearchAccountProviderView-Night-7_9_null_1,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.theme.components_SearchBarActiveNoneQuery_null_Searchviews_SearchBarActiveNoneQuery_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_SearchBarActiveWithContent_null_Searchviews_SearchBarActiveWithContent_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[l.designsystem.theme.components_SearchBarActiveWithNoResults_null_Searchviews_SearchBarActiveWithNoResults_0_null,NEXUS_5,1.0,en]","",1,], +["ui_S_t[l.designsystem.theme.components_SearchBarActiveWithNoResults_null_Searchviews_SearchBarActiveWithNoResults_0_null,NEXUS_5,1.0,en]","",19828,], ["ui_S_t[l.designsystem.theme.components_SearchBarActiveWithQueryNoBackButton_null_Searchviews_SearchBarActiveWithQueryNoBackButton_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_SearchBarActiveWithQuery_null_Searchviews_SearchBarActiveWithQuery_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_SearchBarInactive_null_Searchviews_SearchBarInactive_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[f.createroom.impl.components_SearchMultipleUsersResultItem_null_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.createroom.impl.components_SearchSingleUserResultItem_null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en]","",1,], -["ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Night-1_3_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Night-1_3_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Night-1_3_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Night-2_4_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Night-2_4_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Night-2_4_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-2_3_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Night-2_4_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_5_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_5_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_5_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_5_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_4,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_5_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_5,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_5_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_6,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_5_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_7,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_5_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_4_null_8,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_5_null_8,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Night-5_7_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Night-5_7_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Night-5_7_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Night-5_7_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-5_6_null_4,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Night-5_7_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Night-4_6_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Night-4_6_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Night-4_6_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Night-4_6_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-4_5_null_4,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Night-4_6_null_4,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.createroom.impl.components_SearchMultipleUsersResultItem_null_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.createroom.impl.components_SearchSingleUserResultItem_null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Night-1_3_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Night-1_3_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Night-1_3_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.disable_SecureBackupDisableView_null_SecureBackupDisableView-Night-1_3_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Night-2_4_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Night-2_4_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Day-2_3_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enable_SecureBackupEnableView_null_SecureBackupEnableView-Night-2_4_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Night-3_5_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Night-3_5_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Night-3_5_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Day-3_4_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_null_SecureBackupEnterRecoveryKeyView-Night-3_5_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-4_6_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-4_6_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-4_6_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-4_6_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_4,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-4_6_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_5,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-4_6_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_6,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-4_6_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_7,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-4_6_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-4_5_null_8,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-4_6_null_8,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Night-6_8_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Night-6_8_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Night-6_8_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Night-6_8_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Day-6_7_null_4,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupViewChange_null_SecureBackupSetupViewChange-Night-6_8_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_0,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Night-5_7_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_1,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Night-5_7_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_2,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Night-5_7_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_3,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Night-5_7_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Day-5_6_null_4,NEXUS_5,1.0,en]","ui_S_t[f.securebackup.impl.setup_SecureBackupSetupView_null_SecureBackupSetupView-Night-5_7_null_4,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.matrix.ui.components_SelectedRoom_null_SelectedRoom-Day-5_6_null,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_SelectedRoom_null_SelectedRoom-Night-5_7_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.matrix.ui.components_SelectedUserCannotRemove_null_SelectedUserCannotRemove-Day-7_8_null,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_SelectedUserCannotRemove_null_SelectedUserCannotRemove-Night-7_9_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.matrix.ui.components_SelectedUser_null_SelectedUser-Day-6_7_null,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_SelectedUser_null_SelectedUser-Night-6_8_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.matrix.ui.components_SelectedUsersList_null_SelectedUsersList-Day-8_9_null,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_SelectedUsersList_null_SelectedUsersList-Night-8_10_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.textcomposer.components_SendButton_null_SendButton-Day-12_13_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer.components_SendButton_null_SendButton-Night-12_14_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.setup.biometric_SetupBiometricView_null_SetupBiometricView-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.biometric_SetupBiometricView_null_SetupBiometricView-Night-2_4_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Night-3_5_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Night-3_5_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_2,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Night-3_5_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_3,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Night-3_5_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_4,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Night-3_5_null_4,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.send_SendLocationView_null_SendLocationView-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.setup.biometric_SetupBiometricView_null_SetupBiometricView-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.biometric_SetupBiometricView_null_SetupBiometricView-Night-2_4_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_0,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Night-3_5_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_1,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Night-3_5_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_2,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Night-3_5_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_3,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Night-3_5_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Day-3_4_null_4,NEXUS_5,1.0,en]","ui_S_t[f.lockscreen.impl.setup.pin_SetupPinView_null_SetupPinView-Night-3_5_null_4,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_1,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_10,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_10,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_7,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_8,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_8,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_9,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_9,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_10,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_10,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_7,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_8,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_8,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_9,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_9,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components.reactionsummary_SheetContent_null_SheetContent-Day-53_53_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.reactionsummary_SheetContent_null_SheetContent-Night-53_54_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_5,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_6,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_7,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_7,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.signedout.impl_SignedOutView_null_SignedOutView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.signedout.impl_SignedOutView_null_SignedOutView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_2,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_3,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_4,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_5,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_6,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Day-1_2_null_7,NEXUS_5,1.0,en]","ui_S_t[f.location.impl.show_ShowLocationView_null_ShowLocationView-Night-1_3_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.signedout.impl_SignedOutView_null_SignedOutView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.signedout.impl_SignedOutView_null_SignedOutView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components.dialogs_SingleSelectionDialogContent_null_Dialogs_SingleSelectionDialogContent_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.dialogs_SingleSelectionDialog_null_SingleSelectionDialog-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.dialogs_SingleSelectionDialog_null_SingleSelectionDialog-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.components.list_SingleSelectionListItemCustomFormattert_null_Listitems_SingleselectionListitem-customformatter_0_null,NEXUS_5,1.0,en]","",0,], @@ -777,28 +783,31 @@ export const screenshots = [ ["ui_S_t[l.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_null_Listitems_SingleselectionListitem-noselection,supportingtext_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.components.list_SingleSelectionListItem_null_Listitems_SingleselectionListitem-noselection_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_Sliders_null_Sliders_Sliders_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[f.login.impl.dialogs_SlidingSyncNotSupportedDialog_null_SlidingSyncNotSupportedDialog-Day-2_3_null,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.dialogs_SlidingSyncNotSupportedDialog_null_SlidingSyncNotSupportedDialog-Night-2_4_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.login.impl.dialogs_SlidingSyncNotSupportedDialog_null_SlidingSyncNotSupportedDialog-Day-2_3_null,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.dialogs_SlidingSyncNotSupportedDialog_null_SlidingSyncNotSupportedDialog-Night-2_4_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.theme.components_SnackbarWithActionAndCloseButton_null_Snackbars_Snackbarwithactionandclosebutton_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_null_Snackbars_Snackbarwithactionandclosebuttononnewline_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_SnackbarWithActionOnNewLine_null_Snackbars_Snackbarwithactiononnewline_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_SnackbarWithAction_null_Snackbars_Snackbarwithaction_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_Snackbar_null_Snackbars_Snackbar_0_null,NEXUS_5,1.0,en]","",0,], +["ui_S_t[l.designsystem.modifiers_SquareSizeModifierInsideSquare_null_SquareSizeModifierInsideSquare_0_null,NEXUS_5,1.0,en]","",0,], +["ui_S_t[l.designsystem.modifiers_SquareSizeModifierLargeHeight_null_SquareSizeModifierLargeHeight_0_null,NEXUS_5,1.0,en]","",0,], +["ui_S_t[l.designsystem.modifiers_SquareSizeModifierLargeWidth_null_SquareSizeModifierLargeWidth_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[f.location.api.internal_StaticMapPlaceholder_null_StaticMapPlaceholder-Day-1_2_null_0,NEXUS_5,1.0,en]","ui_S_t[f.location.api.internal_StaticMapPlaceholder_null_StaticMapPlaceholder-Night-1_3_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.location.api.internal_StaticMapPlaceholder_null_StaticMapPlaceholder-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.location.api.internal_StaticMapPlaceholder_null_StaticMapPlaceholder-Night-1_3_null_1,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.location.api.internal_StaticMapPlaceholder_null_StaticMapPlaceholder-Day-1_2_null_1,NEXUS_5,1.0,en]","ui_S_t[f.location.api.internal_StaticMapPlaceholder_null_StaticMapPlaceholder-Night-1_3_null_1,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.location.api_StaticMapView_null_StaticMapView-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[f.location.api_StaticMapView_null_StaticMapView-Night-0_2_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.atomic.pages_SunsetPage_null_SunsetPage-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.pages_SunsetPage_null_SunsetPage-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.theme.components_Surface_null_Surface_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_Switch_null_Toggles_Switch_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[appnav.loggedin_SyncStateView_null_SyncStateView-Day-1_1_null,NEXUS_5,1.0,en]","ui_S_t[appnav.loggedin_SyncStateView_null_SyncStateView-Night-1_2_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[appnav.loggedin_SyncStateView_null_SyncStateView-Day-1_1_null,NEXUS_5,1.0,en]","ui_S_t[appnav.loggedin_SyncStateView_null_SyncStateView-Night-1_2_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.theme.components_TextButtonLarge_null_Buttons_TextButtonLarge_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_TextButtonMedium_null_Buttons_TextButtonMedium_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[l.textcomposer_TextComposerEdit_null_TextComposerEdit-Day-2_3_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerEdit_null_TextComposerEdit-Night-2_4_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Night-1_3_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_null_TextComposerLinkDialogCreateLinkWithoutText-Day-6_7_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_null_TextComposerLinkDialogCreateLinkWithoutText-Night-6_8_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.textcomposer_TextComposerLinkDialogCreateLink_null_TextComposerLinkDialogCreateLink-Day-5_6_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerLinkDialogCreateLink_null_TextComposerLinkDialogCreateLink-Night-5_7_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.textcomposer_TextComposerLinkDialogEditLink_null_TextComposerLinkDialogEditLink-Day-7_8_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerLinkDialogEditLink_null_TextComposerLinkDialogEditLink-Night-7_9_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.textcomposer_TextComposerReply_null_TextComposerReply-Day-3_4_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerReply_null_TextComposerReply-Night-3_5_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Night-0_2_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[l.textcomposer_TextComposerEdit_null_TextComposerEdit-Day-2_3_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerEdit_null_TextComposerEdit-Night-2_4_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Night-1_3_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_null_TextComposerLinkDialogCreateLinkWithoutText-Day-6_7_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_null_TextComposerLinkDialogCreateLinkWithoutText-Night-6_8_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.textcomposer_TextComposerLinkDialogCreateLink_null_TextComposerLinkDialogCreateLink-Day-5_6_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerLinkDialogCreateLink_null_TextComposerLinkDialogCreateLink-Night-5_7_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.textcomposer_TextComposerLinkDialogEditLink_null_TextComposerLinkDialogEditLink-Day-7_8_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerLinkDialogEditLink_null_TextComposerLinkDialogEditLink-Night-7_9_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.textcomposer_TextComposerReply_null_TextComposerReply-Day-3_4_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerReply_null_TextComposerReply-Night-3_5_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Day-0_1_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Night-0_2_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.textcomposer_TextComposerVoice_null_TextComposerVoice-Day-4_5_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer_TextComposerVoice_null_TextComposerVoice-Night-4_6_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.theme.components_TextDark_null_Text_TextDark_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.designsystem.theme.components_TextFieldDark_null_TextFields_TextFieldDark_0_null,NEXUS_5,1.0,en]","",0,], @@ -810,66 +819,66 @@ export const screenshots = [ ["ui_S_t[l.designsystem.theme.components_TextFieldValueTextFieldDark_null_TextFields_TextFieldValueTextFieldDark_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[l.textcomposer.components_TextFormatting_null_TextFormatting-Day-13_14_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer.components_TextFormatting_null_TextFormatting-Night-13_15_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.theme.components_TextLight_null_Text_TextLight_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[l.designsystem.theme.components.previews_TimePickerHorizontal_null_DateTimepickers_TimePickerHorizontal_0_null,NEXUS_5,1.0,en]","",1,], -["ui_S_t[l.designsystem.theme.components.previews_TimePickerVerticalDark_null_DateTimepickers_TimePickerVerticalDark_0_null,NEXUS_5,1.0,en]","",1,], -["ui_S_t[l.designsystem.theme.components.previews_TimePickerVerticalLight_null_DateTimepickers_TimePickerVerticalLight_0_null,NEXUS_5,1.0,en]","",1,], +["ui_S_t[l.designsystem.theme.components.previews_TimePickerHorizontal_null_DateTimepickers_TimePickerHorizontal_0_null,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[l.designsystem.theme.components.previews_TimePickerVerticalDark_null_DateTimepickers_TimePickerVerticalDark_0_null,NEXUS_5,1.0,en]","",19828,], +["ui_S_t[l.designsystem.theme.components.previews_TimePickerVerticalLight_null_DateTimepickers_TimePickerVerticalLight_0_null,NEXUS_5,1.0,en]","",19828,], ["ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Day-15_15_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Night-15_16_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Day-15_15_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Night-15_16_null_1,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Day-15_15_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Night-15_16_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Day-15_15_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Night-15_16_null_3,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Day-15_15_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Night-15_16_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Day-15_15_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineEventTimestampView_null_TimelineEventTimestampView-Night-15_16_null_3,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_null_TimelineImageWithCaptionRow-Day-37_37_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_null_TimelineImageWithCaptionRow-Night-37_38_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-33_33_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-33_34_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-33_33_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-33_34_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-33_33_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-33_34_null_2,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Day-58_58_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Night-58_59_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Day-58_58_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Night-58_59_null_1,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Day-34_34_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Night-34_35_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Day-34_34_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Night-34_35_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_null_TimelineItemEventRowForDirectRoom-Day-17_17_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_null_TimelineItemEventRowForDirectRoom-Night-17_18_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowLongSenderName_null_TimelineItemEventRowLongSenderName_0_null,NEXUS_5,1.0,en]","",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_1,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Day-19_19_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Night-19_20_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Day-19_19_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Night-19_20_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-20_20_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-20_21_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-20_20_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-20_21_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-20_20_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-20_21_null_2,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_null_TimelineItemEventRowWithReplyInformative-Day-21_21_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_null_TimelineItemEventRowWithReplyInformative-Night-21_22_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_null_TimelineItemEventRowWithReplyInformative-Day-21_21_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_null_TimelineItemEventRowWithReplyInformative-Night-21_22_null_1,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_null_TimelineItemEventRowWithReplyInformative-Day-21_21_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_null_TimelineItemEventRowWithReplyInformative-Night-21_22_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_null_TimelineItemEventRowWithReplyInformative-Day-21_21_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_null_TimelineItemEventRowWithReplyInformative-Night-21_22_null_1,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_10,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_10,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_11,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_11,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_2,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_3,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_4,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_4,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_5,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_6,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_6,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_7,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_7,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_8,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_8,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_8,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_8,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-22_22_null_9,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-22_23_null_9,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRow_null_TimelineItemEventRow-Day-16_16_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRow_null_TimelineItemEventRow-Night-16_17_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventTimestampBelow_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en]","",1,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemEventTimestampBelow_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en]","",19828,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-35_35_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-35_36_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-35_35_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-35_36_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-35_35_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-35_36_null_2,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Day-24_24_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Night-24_25_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Day-23_23_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Night-23_24_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Day-24_24_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Night-24_25_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Day-23_23_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Night-23_24_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-36_36_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-36_37_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-36_36_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-36_37_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-36_36_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-36_37_null_2,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemInformativeView_null_TimelineItemInformativeView-Day-38_38_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemInformativeView_null_TimelineItemInformativeView-Night-38_39_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_null_TimelineItemLegacyCallInviteView-Day-39_39_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_null_TimelineItemLegacyCallInviteView-Night-39_40_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_null_TimelineItemLegacyCallInviteView-Day-39_39_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_null_TimelineItemLegacyCallInviteView-Night-39_40_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Day-40_40_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Night-40_41_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Day-40_40_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Night-40_41_null_1,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-41_41_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-41_42_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-41_41_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-41_42_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-41_41_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-41_42_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-41_41_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-41_42_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Day-25_25_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Night-25_26_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-41_41_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-41_42_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-41_41_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-41_42_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-41_41_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-41_42_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-41_41_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-41_42_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Day-25_25_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Night-25_26_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewFew_null_TimelineItemReactionsViewFew-Day-27_27_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewFew_null_TimelineItemReactionsViewFew-Night-27_28_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Day-28_28_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Night-28_29_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Day-29_29_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Night-29_30_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Day-28_28_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Night-28_29_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Day-29_29_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Night-29_30_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-26_26_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-26_27_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-54_54_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-54_55_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-54_54_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-54_55_null_1,NEXUS_5,1.0,en]",0,], @@ -879,9 +888,9 @@ export const screenshots = [ ["ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-54_54_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-54_55_null_5,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-54_54_null_6,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-54_55_null_6,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-54_54_null_7,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-54_55_null_7,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Day-59_59_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Night-59_60_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Day-42_42_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Night-42_43_null,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Day-60_60_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Night-60_61_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Day-59_59_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Night-59_60_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Day-42_42_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Night-42_43_null,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Day-60_60_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Night-60_61_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components_TimelineItemStateEventRow_null_TimelineItemStateEventRow-Day-30_30_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components_TimelineItemStateEventRow_null_TimelineItemStateEventRow-Night-30_31_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStateView_null_TimelineItemStateView-Day-43_43_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStateView_null_TimelineItemStateView-Night-43_44_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStickerView_null_TimelineItemStickerView-Day-44_44_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStickerView_null_TimelineItemStickerView-Night-44_45_null_0,NEXUS_5,1.0,en]",0,], @@ -893,7 +902,7 @@ export const screenshots = [ ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-45_45_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-45_46_null_3,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-45_45_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-45_46_null_4,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-45_45_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-45_46_null_5,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Day-46_46_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Night-46_47_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Day-46_46_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Night-46_47_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-47_47_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-47_48_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-47_47_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-47_48_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-47_47_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-47_48_null_2,NEXUS_5,1.0,en]",0,], @@ -915,22 +924,22 @@ export const screenshots = [ ["ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-49_49_null_9,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-49_50_null_9,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_null_TimelineLoadingMoreIndicator-Day-61_61_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_null_TimelineLoadingMoreIndicator-Night-61_62_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_null_TimelineVideoWithCaptionRow-Day-48_48_null,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_null_TimelineVideoWithCaptionRow-Night-48_49_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_1,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_1,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_10,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_10,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_11,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_11,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_12,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_12,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_13,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_13,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_14,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_14,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_15,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_15,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_16,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_16,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_11,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_11,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_12,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_12,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_13,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_13,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_14,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_14,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_15,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_15,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_16,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_16,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_2,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_3,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_4,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_4,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_5,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_6,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_6,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_6,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_6,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_7,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_7,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_8,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_8,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_8,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_8,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_9,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_9,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.components_TitleWithIconFull_null_TitleWithIconFull-Day_0_null_0,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_TitleWithIconFull_null_TitleWithIconFull-Night_1_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.components_TitleWithIconFull_null_TitleWithIconFull-Day_0_null_1,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_TitleWithIconFull_null_TitleWithIconFull-Night_1_null_1,NEXUS_5,1.0,en]",0,], @@ -939,48 +948,51 @@ export const screenshots = [ ["ui_S_t[l.designsystem.components_TitleWithIconFull_null_TitleWithIconFull-Day_0_null_4,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_TitleWithIconFull_null_TitleWithIconFull-Night_1_null_4,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.components_TitleWithIconMinimal_null_TitleWithIconMinimal-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components_TitleWithIconMinimal_null_TitleWithIconMinimal-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.theme.components_TopAppBar_null_AppBars_TopAppBar_0_null,NEXUS_5,1.0,en]","",0,], -["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_7,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_7,NEXUS_5,1.0,en]",1,], +["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Day-0_1_null_7,NEXUS_5,1.0,en]","ui_S_t[l.troubleshoot.impl_TroubleshootNotificationsView_null_TroubleshootNotificationsView-Night-0_2_null_7,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_0,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_0,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_6,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_6,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_1,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_2,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_3,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_4,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_5,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_6,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_6,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_7,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_7,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Day-64_64_null_8,NEXUS_5,1.0,en]","ui_S_t[f.messages.impl.typing_TypingNotificationView_null_TypingNotificationView-Night-64_65_null_8,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.atomic.atoms_UnreadIndicatorAtom_null_UnreadIndicatorAtom-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.atomic.atoms_UnreadIndicatorAtom_null_UnreadIndicatorAtom-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[l.matrix.ui.components_UnresolvedUserRow_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en]","",1,], +["ui_S_t[l.matrix.ui.components_UnresolvedUserRow_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en]","",19828,], ["ui_S_t[l.matrix.ui.components_UnsavedAvatar_null_UnsavedAvatar-Day-9_10_null,NEXUS_5,1.0,en]","ui_S_t[l.matrix.ui.components_UnsavedAvatar_null_UnsavedAvatar-Night-9_11_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.designsystem.components.avatar_UserAvatar_null_UserAvatar-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.avatar_UserAvatar_null_UserAvatar-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettings_null_UserDefinedRoomNotificationSettings-Day-7_8_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettings_null_UserDefinedRoomNotificationSettings-Night-7_9_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_1,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_2,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_2,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettings_null_UserDefinedRoomNotificationSettings-Day-7_8_null_0,NEXUS_5,1.0,en]","ui_S_t[f.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettings_null_UserDefinedRoomNotificationSettings-Night-7_9_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_0,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_1,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_2,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_2,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_3,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_3,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_4,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_4,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_5,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_5,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_6,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_6,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_7,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_7,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_7,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_7,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_8,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_8,NEXUS_5,1.0,en]",0,], +["ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Day-2_3_null_9,NEXUS_5,1.0,en]","ui_S_t[f.createroom.impl.components_UserListView_null_UserListView-Night-2_4_null_9,NEXUS_5,1.0,en]",19828,], ["ui_S_t[f.preferences.impl.user_UserPreferences_null_UserPreferences-Day-9_10_null_0,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.user_UserPreferences_null_UserPreferences-Night-9_11_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.preferences.impl.user_UserPreferences_null_UserPreferences-Day-9_10_null_1,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.user_UserPreferences_null_UserPreferences-Night-9_11_null_1,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.preferences.impl.user_UserPreferences_null_UserPreferences-Day-9_10_null_2,NEXUS_5,1.0,en]","ui_S_t[f.preferences.impl.user_UserPreferences_null_UserPreferences-Night-9_11_null_2,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_4,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_5,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_6,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_7,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_7,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_2,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_3,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_4,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_4,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_5,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_5,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_6,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_6,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_7,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_7,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_8,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_8,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_9,NEXUS_5,1.0,en]","ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_9,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.ruler_VerticalRuler_null_VerticalRuler-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.ruler_VerticalRuler_null_VerticalRuler-Night_1_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Day-0_1_null_0,NEXUS_5,1.0,en]","ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Night-0_2_null_0,NEXUS_5,1.0,en]",0,], ["ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Day-0_1_null_1,NEXUS_5,1.0,en]","ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Night-0_2_null_1,NEXUS_5,1.0,en]",0,], @@ -994,12 +1006,12 @@ export const screenshots = [ ["ui_S_t[l.textcomposer.components_VoiceMessagePreview_null_VoiceMessagePreview-Day-15_16_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer.components_VoiceMessagePreview_null_VoiceMessagePreview-Night-15_17_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.textcomposer.components_VoiceMessageRecorderButton_null_VoiceMessageRecorderButton-Day-16_17_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer.components_VoiceMessageRecorderButton_null_VoiceMessageRecorderButton-Night-16_18_null,NEXUS_5,1.0,en]",0,], ["ui_S_t[l.textcomposer.components_VoiceMessageRecording_null_VoiceMessageRecording-Day-17_18_null,NEXUS_5,1.0,en]","ui_S_t[l.textcomposer.components_VoiceMessageRecording_null_VoiceMessageRecording-Night-17_19_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Day-8_9_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Night-8_10_null_0,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Day-8_9_null_1,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Night-8_10_null_1,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Day-8_9_null_2,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Night-8_10_null_2,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Day-8_9_null_3,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Night-8_10_null_3,NEXUS_5,1.0,en]",1,], -["ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Day-8_9_null_4,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Night-8_10_null_4,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Day-8_9_null_0,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Night-8_10_null_0,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Day-8_9_null_1,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Night-8_10_null_1,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Day-8_9_null_2,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Night-8_10_null_2,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Day-8_9_null_3,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Night-8_10_null_3,NEXUS_5,1.0,en]",19828,], +["ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Day-8_9_null_4,NEXUS_5,1.0,en]","ui_S_t[f.login.impl.screens.waitlistscreen_WaitListView_null_WaitListView-Night-8_10_null_4,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.components.media_WaveformPlaybackView_null_WaveformPlaybackView-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.components.media_WaveformPlaybackView_null_WaveformPlaybackView-Night_1_null,NEXUS_5,1.0,en]",0,], -["ui_S_t[f.ftue.impl.welcome_WelcomeView_null_WelcomeView-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.ftue.impl.welcome_WelcomeView_null_WelcomeView-Night-1_3_null,NEXUS_5,1.0,en]",1,], +["ui_S_t[f.ftue.impl.welcome_WelcomeView_null_WelcomeView-Day-1_2_null,NEXUS_5,1.0,en]","ui_S_t[f.ftue.impl.welcome_WelcomeView_null_WelcomeView-Night-1_3_null,NEXUS_5,1.0,en]",19828,], ["ui_S_t[l.designsystem.ruler_WithRuler_null_WithRuler-Day_0_null,NEXUS_5,1.0,en]","ui_S_t[l.designsystem.ruler_WithRuler_null_WithRuler-Night_1_null,NEXUS_5,1.0,en]",0,], ]; From 933263ee96ade41561813db670e2e8747e45c4b1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 13:42:37 +0200 Subject: [PATCH 41/52] Remove unnecessary Box wrapping. --- .../button/GradientFloatingActionButton.kt | 84 +++++++------- .../components/button/SuperButton.kt | 104 +++++++++--------- 2 files changed, 92 insertions(+), 96 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/GradientFloatingActionButton.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/GradientFloatingActionButton.kt index d600f92326..dcce83644c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/GradientFloatingActionButton.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/GradientFloatingActionButton.kt @@ -59,56 +59,54 @@ fun GradientFloatingActionButton( shape: Shape = RoundedCornerShape(25), content: @Composable () -> Unit, ) { - Box { - val linearShaderBrush = remember { - object : ShaderBrush() { - override fun createShader(size: Size): Shader { - return LinearGradientShader( - from = Offset(size.width, size.height), - to = Offset(size.width, 0f), - colors = listOf( - LightColorTokens.colorBlue900, - LightColorTokens.colorGreen700, - ), - ) - } + val linearShaderBrush = remember { + object : ShaderBrush() { + override fun createShader(size: Size): Shader { + return LinearGradientShader( + from = Offset(size.width, size.height), + to = Offset(size.width, 0f), + colors = listOf( + LightColorTokens.colorBlue900, + LightColorTokens.colorGreen700, + ), + ) } } - val radialShaderBrush = remember { - object : ShaderBrush() { - override fun createShader(size: Size): Shader { - return RadialGradientShader( - center = size.center, - radius = size.width / 2, - colors = listOf( - LightColorTokens.colorGreen700, - LightColorTokens.colorBlue900, - ) + } + val radialShaderBrush = remember { + object : ShaderBrush() { + override fun createShader(size: Size): Shader { + return RadialGradientShader( + center = size.center, + radius = size.width / 2, + colors = listOf( + LightColorTokens.colorGreen700, + LightColorTokens.colorBlue900, ) - } + ) } } + } - Box( - modifier = modifier - .minimumInteractiveComponentSize() - .graphicsLayer(shape = shape, clip = false) - .clip(shape) - .drawBehind { - drawRect(brush = radialShaderBrush, alpha = 0.4f) - drawRect(brush = linearShaderBrush) - } - .clickable( - enabled = true, - onClick = onClick, - interactionSource = remember { MutableInteractionSource() }, - indication = rememberRipple(color = Color.White) - ), - contentAlignment = Alignment.Center - ) { - CompositionLocalProvider(LocalContentColor provides Color.White) { - content() + Box( + modifier = modifier + .minimumInteractiveComponentSize() + .graphicsLayer(shape = shape, clip = false) + .clip(shape) + .drawBehind { + drawRect(brush = radialShaderBrush, alpha = 0.4f) + drawRect(brush = linearShaderBrush) } + .clickable( + enabled = true, + onClick = onClick, + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(color = Color.White) + ), + contentAlignment = Alignment.Center + ) { + CompositionLocalProvider(LocalContentColor provides Color.White) { + content() } } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt index dbd03091ed..1bbbc1c123 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt @@ -71,64 +71,62 @@ fun SuperButton( ButtonSize.Small -> PaddingValues(horizontal = 16.dp, vertical = 5.dp) } } - Box { - val isLightTheme = ElementTheme.isLightTheme - val colors = remember(isLightTheme) { - if (isLightTheme) { - listOf( - LightColorTokens.colorBlue900, - LightColorTokens.colorGreen1100, - ) - } else { - listOf( - DarkColorTokens.colorBlue900, - DarkColorTokens.colorGreen1100, - ) - } + val isLightTheme = ElementTheme.isLightTheme + val colors = remember(isLightTheme) { + if (isLightTheme) { + listOf( + LightColorTokens.colorBlue900, + LightColorTokens.colorGreen1100, + ) + } else { + listOf( + DarkColorTokens.colorBlue900, + DarkColorTokens.colorGreen1100, + ) } + } - val shaderBrush = remember(colors) { - object : ShaderBrush() { - override fun createShader(size: Size): Shader { - return LinearGradientShader( - from = Offset(0f, size.height), - to = Offset(size.width, 0f), - colors = colors, - ) - } + val shaderBrush = remember(colors) { + object : ShaderBrush() { + override fun createShader(size: Size): Shader { + return LinearGradientShader( + from = Offset(0f, size.height), + to = Offset(size.width, 0f), + colors = colors, + ) } } - val border = if (enabled) { - BorderStroke(1.dp, shaderBrush) - } else { - BorderStroke(1.dp, ElementTheme.colors.borderDisabled) - } - val backgroundColor = ElementTheme.colors.bgCanvasDefault - Box( - modifier = modifier - .minimumInteractiveComponentSize() - .graphicsLayer(shape = shape, clip = false) - .clip(shape) - .border(border, shape) - .drawBehind { - drawRect(backgroundColor) - drawRect(brush = shaderBrush, alpha = 0.04f) - } - .clickable( - enabled = enabled, - onClick = onClick, - interactionSource = remember { MutableInteractionSource() }, - indication = rememberRipple() - ) - .padding(contentPadding), - contentAlignment = Alignment.Center - ) { - CompositionLocalProvider( - LocalContentColor provides if (enabled) ElementTheme.colors.textPrimary else ElementTheme.colors.textDisabled, - LocalTextStyle provides ElementTheme.typography.fontBodyLgMedium, - ) { - content() + } + val border = if (enabled) { + BorderStroke(1.dp, shaderBrush) + } else { + BorderStroke(1.dp, ElementTheme.colors.borderDisabled) + } + val backgroundColor = ElementTheme.colors.bgCanvasDefault + Box( + modifier = modifier + .minimumInteractiveComponentSize() + .graphicsLayer(shape = shape, clip = false) + .clip(shape) + .border(border, shape) + .drawBehind { + drawRect(backgroundColor) + drawRect(brush = shaderBrush, alpha = 0.04f) } + .clickable( + enabled = enabled, + onClick = onClick, + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple() + ) + .padding(contentPadding), + contentAlignment = Alignment.Center + ) { + CompositionLocalProvider( + LocalContentColor provides if (enabled) ElementTheme.colors.textPrimary else ElementTheme.colors.textDisabled, + LocalTextStyle provides ElementTheme.typography.fontBodyLgMedium, + ) { + content() } } } From 88b3c33eaf41ef88060819ac4f5a228593245eb4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 14:17:42 +0200 Subject: [PATCH 42/52] Format --- .../libraries/designsystem/components/button/SuperButton.kt | 1 - .../android/libraries/designsystem/theme/components/Button.kt | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt index 1bbbc1c123..56da5f5211 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/SuperButton.kt @@ -191,4 +191,3 @@ internal fun SuperButtonPreview() { } } } - diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt index b832c49587..c4e2f16fc2 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt @@ -203,7 +203,8 @@ private fun ButtonInternal( } val textStyle = when (size) { - ButtonSize.Small, ButtonSize.Medium -> MaterialTheme.typography.labelLarge + ButtonSize.Small, + ButtonSize.Medium -> MaterialTheme.typography.labelLarge ButtonSize.Large -> ElementTheme.typography.fontBodyLgMedium } From 294f1f2d96e3d1b61ea9d954f376a134417e6ef7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 9 Apr 2024 11:45:43 +0200 Subject: [PATCH 43/52] Use SDK API to build room and event permalinks. --- .../messages/impl/MessagesPresenterTest.kt | 2 +- .../roomdetails/impl/RoomDetailsNode.kt | 32 +++++++++-------- .../matrix/api/permalink/PermalinkBuilder.kt | 5 --- .../libraries/matrix/api/room/MatrixRoom.kt | 5 +++ .../impl/permalink/DefaultPermalinkBuilder.kt | 31 ---------------- .../matrix/impl/room/RustMatrixRoom.kt | 18 ++++------ .../permalink/DefaultPermalinkBuilderTest.kt | 35 +------------------ .../test/permalink/FakePermalinkBuilder.kt | 9 ----- .../matrix/test/room/FakeMatrixRoom.kt | 9 +++-- 9 files changed, 37 insertions(+), 109 deletions(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index ab604e468e..002b34f0eb 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 @@ -236,7 +236,7 @@ class MessagesPresenterTest { val clipboardHelper = FakeClipboardHelper() val event = aMessageEvent() val matrixRoom = FakeMatrixRoom( - permalinkResult = { Result.success("a link") }, + eventPermalinkResult = { Result.success("a link") }, ) val presenter = createMessagesPresenter( clipboardHelper = clipboardHelper, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt index 6bf8b00dd7..562e34bb38 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt @@ -18,6 +18,7 @@ package io.element.android.features.roomdetails.impl import android.content.Context import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import com.bumble.appyx.core.lifecycle.subscribe @@ -35,6 +36,8 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.services.analytics.api.AnalyticsService +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import timber.log.Timber import io.element.android.libraries.androidutils.R as AndroidUtilsR @@ -83,20 +86,18 @@ class RoomDetailsNode @AssistedInject constructor( callbacks.forEach { it.openPollHistory() } } - private fun onShareRoom(context: Context) { - val alias = room.alias ?: room.alternativeAliases.firstOrNull() - val permalinkResult = alias?.let { permalinkBuilder.permalinkForRoomAlias(it) } - ?: permalinkBuilder.permalinkForRoomId(room.roomId) - permalinkResult.onSuccess { permalink -> - context.startSharePlainTextIntent( - activityResultLauncher = null, - chooserTitle = context.getString(R.string.screen_room_details_share_room_title), - text = permalink, - noActivityFoundMessage = context.getString(AndroidUtilsR.string.error_no_compatible_app_found) - ) - }.onFailure { - Timber.e(it) - } + private fun CoroutineScope.onShareRoom(context: Context) = launch { + room.getPermalink() + .onSuccess { permalink -> + context.startSharePlainTextIntent( + activityResultLauncher = null, + chooserTitle = context.getString(R.string.screen_room_details_share_room_title), + text = permalink, + noActivityFoundMessage = context.getString(AndroidUtilsR.string.error_no_compatible_app_found) + ) + }.onFailure { + Timber.e(it) + } } private fun onShareMember(context: Context, member: RoomMember) { @@ -129,9 +130,10 @@ class RoomDetailsNode @AssistedInject constructor( override fun View(modifier: Modifier) { val context = LocalContext.current val state = presenter.present() + val coroutineScope = rememberCoroutineScope() fun onShareRoom() { - this.onShareRoom(context) + coroutineScope.onShareRoom(context) } fun onShareMember(roomMember: RoomMember) { diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt index 14c29f2de5..76bb327c2e 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt @@ -16,17 +16,12 @@ package io.element.android.libraries.matrix.api.permalink -import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId interface PermalinkBuilder { fun permalinkForUser(userId: UserId): Result - fun permalinkForRoomAlias(roomAlias: String): Result - fun permalinkForRoomId(roomId: RoomId): Result } sealed class PermalinkBuilderError : Throwable() { - data object InvalidRoomAlias : PermalinkBuilderError() - data object InvalidRoomId : PermalinkBuilderError() data object InvalidUserId : PermalinkBuilderError() } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 07b5b310bc..761d87445a 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -317,6 +317,11 @@ interface MatrixRoom : Closeable { */ fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result + /** + * Get the permalink for the room. + */ + suspend fun getPermalink(): Result + /** * Get the permalink for the provided [eventId]. * @param eventId The event id to get the permalink for. diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt index ae30c94c9c..42599c5e64 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt @@ -20,7 +20,6 @@ import com.squareup.anvil.annotations.ContributesBinding import io.element.android.appconfig.MatrixConfiguration import io.element.android.libraries.di.AppScope import io.element.android.libraries.matrix.api.core.MatrixPatterns -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.PermalinkBuilder import io.element.android.libraries.matrix.api.permalink.PermalinkBuilderError @@ -54,39 +53,9 @@ class DefaultPermalinkBuilder @Inject constructor() : PermalinkBuilder { } } - override fun permalinkForRoomAlias(roomAlias: String): Result { - return if (MatrixPatterns.isRoomAlias(roomAlias)) { - Result.success(permalinkForRoomAliasOrId(roomAlias)) - } else { - Result.failure(PermalinkBuilderError.InvalidRoomAlias) - } - } - - override fun permalinkForRoomId(roomId: RoomId): Result { - return if (MatrixPatterns.isRoomId(roomId.value)) { - Result.success(permalinkForRoomAliasOrId(roomId.value)) - } else { - Result.failure(PermalinkBuilderError.InvalidRoomId) - } - } - - private fun permalinkForRoomAliasOrId(value: String): String { - val id = escapeId(value) - return buildString { - append(permalinkBaseUrl) - if (!isMatrixTo()) { - append(ROOM_PATH) - } - append(id) - } - } - - private fun escapeId(value: String) = value.replace("/", "%2F") - private fun isMatrixTo(): Boolean = permalinkBaseUrl.startsWith(MatrixConfiguration.MATRIX_TO_PERMALINK_BASE_URL) companion object { - private const val ROOM_PATH = "room/" private const val USER_PATH = "user/" } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 0531c59d4a..59e5c99efa 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -16,7 +16,6 @@ package io.element.android.libraries.matrix.impl.room -import io.element.android.appconfig.MatrixConfiguration import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.childScope import io.element.android.libraries.matrix.api.core.EventId @@ -731,17 +730,12 @@ class RustMatrixRoom( ) } - override suspend fun getPermalinkFor(eventId: EventId): Result { - // FIXME Use the SDK API once https://github.com/matrix-org/matrix-rust-sdk/issues/3259 has been done - // Now use a simple builder - return runCatching { - buildString { - append(MatrixConfiguration.MATRIX_TO_PERMALINK_BASE_URL) - append(roomId.value) - append("/") - append(eventId.value) - } - } + override suspend fun getPermalink(): Result = runCatching { + innerRoom.matrixToPermalink() + } + + override suspend fun getPermalinkFor(eventId: EventId): Result = runCatching { + innerRoom.matrixToEventPermalink(eventId.value) } private fun sendAttachment(files: List, handle: () -> SendAttachmentJoinHandle): Result { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilderTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilderTest.kt index c861b3105c..bebb46cf85 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilderTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilderTest.kt @@ -18,12 +18,12 @@ package io.element.android.libraries.matrix.impl.permalink import com.google.common.truth.Truth.assertThat import io.element.android.libraries.androidutils.metadata.withReleaseBehavior -import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.tests.testutils.assertThrowsInDebug import org.junit.Test class DefaultPermalinkBuilderTest { + @Test fun `building a permalink for an invalid user id throws when verifying the id`() { assertThrowsInDebug { val userId = UserId("some invalid user id") @@ -31,13 +31,6 @@ class DefaultPermalinkBuilderTest { } } - fun `building a permalink for an invalid room id throws when verifying the id`() { - assertThrowsInDebug { - val roomId = RoomId("some invalid room id") - DefaultPermalinkBuilder().permalinkForRoomId(roomId) - } - } - @Test fun `building a permalink for an invalid user id returns failure when not verifying the id`() { withReleaseBehavior { @@ -46,35 +39,9 @@ class DefaultPermalinkBuilderTest { } } - @Test - fun `building a permalink for an invalid room id returns failure when not verifying the id`() { - withReleaseBehavior { - val roomId = RoomId("some invalid room id") - assertThat(DefaultPermalinkBuilder().permalinkForRoomId(roomId).isFailure).isTrue() - } - } - - @Test - fun `building a permalink for an invalid room alias returns failure`() { - val roomAlias = "an invalid room alias" - assertThat(DefaultPermalinkBuilder().permalinkForRoomAlias(roomAlias).isFailure).isTrue() - } - @Test fun `building a permalink for a valid user id returns a matrix-to url`() { val userId = UserId("@user:matrix.org") assertThat(DefaultPermalinkBuilder().permalinkForUser(userId).getOrNull()).isEqualTo("https://matrix.to/#/@user:matrix.org") } - - @Test - fun `building a permalink for a valid room id returns a matrix-to url`() { - val roomId = RoomId("!aBCdEFG1234:matrix.org") - assertThat(DefaultPermalinkBuilder().permalinkForRoomId(roomId).getOrNull()).isEqualTo("https://matrix.to/#/!aBCdEFG1234:matrix.org") - } - - @Test - fun `building a permalink for a valid room alias returns a matrix-to url`() { - val roomAlias = "#room:matrix.org" - assertThat(DefaultPermalinkBuilder().permalinkForRoomAlias(roomAlias).getOrNull()).isEqualTo("https://matrix.to/#/#room:matrix.org") - } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkBuilder.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkBuilder.kt index 4e6d3375e1..273899e762 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkBuilder.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkBuilder.kt @@ -16,7 +16,6 @@ package io.element.android.libraries.matrix.test.permalink -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.PermalinkBuilder @@ -26,12 +25,4 @@ class FakePermalinkBuilder( override fun permalinkForUser(userId: UserId): Result { return result() } - - override fun permalinkForRoomAlias(roomAlias: String): Result { - return result() - } - - override fun permalinkForRoomId(roomId: RoomId): Result { - return result() - } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 0de64514b7..5938cd300b 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -84,7 +84,8 @@ class FakeMatrixRoom( override val activeMemberCount: Long = 234L, val notificationSettingsService: NotificationSettingsService = FakeNotificationSettingsService(), private val matrixTimeline: MatrixTimeline = FakeMatrixTimeline(), - private var permalinkResult: () -> Result = { Result.success("link") }, + private var roomPermalinkResult: () -> Result = { Result.success("room link") }, + private var eventPermalinkResult: (EventId) -> Result = { Result.success("event link") }, canRedactOwn: Boolean = false, canRedactOther: Boolean = false, ) : MatrixRoom { @@ -278,8 +279,12 @@ class FakeMatrixRoom( return cancelSendResult } + override suspend fun getPermalink(): Result { + return roomPermalinkResult() + } + override suspend fun getPermalinkFor(eventId: EventId): Result { - return permalinkResult() + return eventPermalinkResult(eventId) } override suspend fun editMessage( From 6b301ac37f13f81d1343f5e348f5bcfe4c7a3b1d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 16:24:56 +0200 Subject: [PATCH 44/52] Use `org.matrix.rustcomponents.sdk.matrixToUserPermalink` to build permalinks for user. --- .../impl/permalink/DefaultPermalinkBuilder.kt | 35 +++----------- .../permalink/DefaultPermalinkBuilderTest.kt | 47 ------------------- 2 files changed, 6 insertions(+), 76 deletions(-) delete mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilderTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt index 42599c5e64..3103ff4c1e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilder.kt @@ -17,45 +17,22 @@ package io.element.android.libraries.matrix.impl.permalink import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.appconfig.MatrixConfiguration import io.element.android.libraries.di.AppScope import io.element.android.libraries.matrix.api.core.MatrixPatterns import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder import io.element.android.libraries.matrix.api.permalink.PermalinkBuilderError +import org.matrix.rustcomponents.sdk.matrixToUserPermalink import javax.inject.Inject @ContributesBinding(AppScope::class) class DefaultPermalinkBuilder @Inject constructor() : PermalinkBuilder { - private val permalinkBaseUrl - get() = (MatrixConfiguration.clientPermalinkBaseUrl ?: MatrixConfiguration.MATRIX_TO_PERMALINK_BASE_URL).also { - var baseUrl = it - if (!baseUrl.endsWith("/")) { - baseUrl += "/" - } - if (!baseUrl.endsWith("/#/")) { - baseUrl += "/#/" - } - } - override fun permalinkForUser(userId: UserId): Result { - return if (MatrixPatterns.isUserId(userId.value)) { - val url = buildString { - append(permalinkBaseUrl) - if (!isMatrixTo()) { - append(USER_PATH) - } - append(userId.value) - } - Result.success(url) - } else { - Result.failure(PermalinkBuilderError.InvalidUserId) + if (!MatrixPatterns.isUserId(userId.value)) { + return Result.failure(PermalinkBuilderError.InvalidUserId) + } + return runCatching { + matrixToUserPermalink(userId.value) } - } - - private fun isMatrixTo(): Boolean = permalinkBaseUrl.startsWith(MatrixConfiguration.MATRIX_TO_PERMALINK_BASE_URL) - - companion object { - private const val USER_PATH = "user/" } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilderTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilderTest.kt deleted file mode 100644 index bebb46cf85..0000000000 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkBuilderTest.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2024 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.element.android.libraries.matrix.impl.permalink - -import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.androidutils.metadata.withReleaseBehavior -import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.tests.testutils.assertThrowsInDebug -import org.junit.Test - -class DefaultPermalinkBuilderTest { - @Test - fun `building a permalink for an invalid user id throws when verifying the id`() { - assertThrowsInDebug { - val userId = UserId("some invalid user id") - DefaultPermalinkBuilder().permalinkForUser(userId) - } - } - - @Test - fun `building a permalink for an invalid user id returns failure when not verifying the id`() { - withReleaseBehavior { - val userId = UserId("some invalid user id") - assertThat(DefaultPermalinkBuilder().permalinkForUser(userId).isFailure).isTrue() - } - } - - @Test - fun `building a permalink for a valid user id returns a matrix-to url`() { - val userId = UserId("@user:matrix.org") - assertThat(DefaultPermalinkBuilder().permalinkForUser(userId).getOrNull()).isEqualTo("https://matrix.to/#/@user:matrix.org") - } -} From 6036a3c7d1704fe9821a76b60d890ea0c19f200a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 16:43:10 +0200 Subject: [PATCH 45/52] Use `org.matrix.rustcomponents.sdk.matrixToUserPermalink` to build permalinks for user. --- changelog.d/2708.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/2708.misc diff --git a/changelog.d/2708.misc b/changelog.d/2708.misc new file mode 100644 index 0000000000..807824f3ab --- /dev/null +++ b/changelog.d/2708.misc @@ -0,0 +1 @@ + Use sdk API to build permalinks From b1cb24a8831cb8086d505548d4a09e410be677a1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 17:02:27 +0200 Subject: [PATCH 46/52] Use Node scope instead of UI scope. --- .../android/features/roomdetails/impl/RoomDetailsNode.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt index 562e34bb38..b08991f11a 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt @@ -18,9 +18,9 @@ package io.element.android.features.roomdetails.impl import android.content.Context import androidx.compose.runtime.Composable -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +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 @@ -130,10 +130,9 @@ class RoomDetailsNode @AssistedInject constructor( override fun View(modifier: Modifier) { val context = LocalContext.current val state = presenter.present() - val coroutineScope = rememberCoroutineScope() fun onShareRoom() { - coroutineScope.onShareRoom(context) + lifecycleScope.onShareRoom(context) } fun onShareMember(roomMember: RoomMember) { From 9fcb880f1d24b1b4f4aecf5183558c18034b517f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 17:04:33 +0200 Subject: [PATCH 47/52] Fix formatting issue. --- .../roomdetails/impl/RoomDetailsNode.kt | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt index b08991f11a..84658ccc83 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt @@ -95,23 +95,26 @@ class RoomDetailsNode @AssistedInject constructor( text = permalink, noActivityFoundMessage = context.getString(AndroidUtilsR.string.error_no_compatible_app_found) ) - }.onFailure { + } + .onFailure { Timber.e(it) } } private fun onShareMember(context: Context, member: RoomMember) { val permalinkResult = permalinkBuilder.permalinkForUser(member.userId) - permalinkResult.onSuccess { permalink -> - context.startSharePlainTextIntent( - activityResultLauncher = null, - chooserTitle = context.getString(R.string.screen_room_details_share_room_title), - text = permalink, - noActivityFoundMessage = context.getString(AndroidUtilsR.string.error_no_compatible_app_found) - ) - }.onFailure { - Timber.e(it) - } + permalinkResult + .onSuccess { permalink -> + context.startSharePlainTextIntent( + activityResultLauncher = null, + chooserTitle = context.getString(R.string.screen_room_details_share_room_title), + text = permalink, + noActivityFoundMessage = context.getString(AndroidUtilsR.string.error_no_compatible_app_found) + ) + } + .onFailure { + Timber.e(it) + } } private fun onEditRoomDetails() { From 3df328b1ab2d446447ec1507d8e3386a8662e51b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 17:46:06 +0200 Subject: [PATCH 48/52] Parse permalink using `parseMatrixEntityFrom`. Create new PermalinkData type for link to Events. Keep matrixToConverter for now to first convert to matrix.to link. At some point it may be done by the SDK. Remove parse(Uri) --- .../features/messages/impl/MessagesNode.kt | 11 +- .../MessageComposerStateProvider.kt | 2 - .../matrix/api/permalink/PermalinkData.kt | 44 ++++-- .../matrix/api/permalink/PermalinkParser.kt | 9 +- .../libraries/matrix/api/room/Mention.kt | 3 +- .../matrix/api/permalink/PermalinkDataTest.kt | 47 ------ .../impl/permalink/DefaultPermalinkParser.kt | 138 +++++------------- .../permalink/DefaultPermalinkParserTest.kt | 54 ++++--- .../test/permalink/FakePermalinkParser.kt | 5 - .../matrixui/messages/ToHtmlDocumentTest.kt | 11 +- .../libraries/textcomposer/TextComposer.kt | 1 - .../mentions/MentionSpanProvider.kt | 16 +- .../impl/mentions/MentionSpanProviderTest.kt | 17 +-- .../minimal/OnlyFallbackPermalinkParser.kt | 4 - 14 files changed, 123 insertions(+), 239 deletions(-) delete mode 100644 libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkDataTest.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index aca840236e..ff8c727f9c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -17,7 +17,6 @@ package io.element.android.features.messages.impl import android.content.Context -import android.net.Uri import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier @@ -108,13 +107,19 @@ class MessagesNode @AssistedInject constructor( context: Context, url: String, ) { - when (val permalink = permalinkParser.parse(Uri.parse(url))) { + when (val permalink = permalinkParser.parse(url)) { is PermalinkData.UserLink -> { - callback?.onUserDataClicked(UserId(permalink.userId)) + callback?.onUserDataClicked(permalink.userId) } is PermalinkData.RoomLink -> { // TODO Implement room link handling } + is PermalinkData.EventIdAliasLink -> { + // TODO Implement room and Event link handling + } + is PermalinkData.EventIdLink -> { + // TODO Implement room and Event link handling + } is PermalinkData.FallbackLink, is PermalinkData.RoomEmailInviteLink -> { context.openUrlInExternalApp(url) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt index 82a4692a53..340f7328f3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt @@ -16,7 +16,6 @@ package io.element.android.features.messages.impl.messagecomposer -import android.net.Uri import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.messages.impl.mentions.MentionSuggestion import io.element.android.libraries.matrix.api.core.UserId @@ -49,7 +48,6 @@ fun aMessageComposerState( richTextEditorState = richTextEditorState, permalinkParser = object : PermalinkParser { override fun parse(uriString: String): PermalinkData = TODO() - override fun parse(uri: Uri): PermalinkData = TODO() }, isFullScreen = isFullScreen, mode = mode, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkData.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkData.kt index e39fee5a22..d09394e8dd 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkData.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkData.kt @@ -18,7 +18,9 @@ package io.element.android.libraries.matrix.api.permalink import android.net.Uri import androidx.compose.runtime.Immutable +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 kotlinx.collections.immutable.ImmutableList /** @@ -27,28 +29,44 @@ import kotlinx.collections.immutable.ImmutableList */ @Immutable sealed interface PermalinkData { - data class RoomLink( - val roomIdOrAlias: String, - val isRoomAlias: Boolean, - val eventId: String?, + sealed interface RoomLink : PermalinkData { val viaParameters: ImmutableList - ) : PermalinkData { - fun getRoomId(): RoomId? { - return roomIdOrAlias.takeIf { !isRoomAlias }?.let(::RoomId) - } + } + + data class RoomIdLink( + val roomId: RoomId, + override val viaParameters: ImmutableList + ) : RoomLink + + data class RoomAliasLink( + val roomAlias: String, + override val viaParameters: ImmutableList + ) : RoomLink - fun getRoomAlias(): String? { - return roomIdOrAlias.takeIf { isRoomAlias } - } + sealed interface EventLink : PermalinkData { + val eventId: EventId + val viaParameters: ImmutableList } + data class EventIdLink( + val roomId: RoomId, + override val eventId: EventId, + override val viaParameters: ImmutableList + ) : EventLink + + data class EventIdAliasLink( + val roomAlias: String, + override val eventId: EventId, + override val viaParameters: ImmutableList + ) : EventLink + /* * &room_name=Team2 * &room_avatar_url=mxc: * &inviter_name=bob */ data class RoomEmailInviteLink( - val roomId: String, + val roomId: RoomId, val email: String, val signUrl: String, val roomName: String?, @@ -60,7 +78,7 @@ sealed interface PermalinkData { val roomType: String? ) : PermalinkData - data class UserLink(val userId: String) : PermalinkData + data class UserLink(val userId: UserId) : PermalinkData data class FallbackLink(val uri: Uri, val isLegacyGroupLink: Boolean = false) : PermalinkData } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParser.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParser.kt index 463f8fb32d..ebe7596aa4 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParser.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParser.kt @@ -16,8 +16,6 @@ package io.element.android.libraries.matrix.api.permalink -import android.net.Uri - /** * This class turns a uri to a [PermalinkData]. * element-based domains (e.g. https://app.element.io/#/user/@chagai95:matrix.org) permalinks @@ -27,12 +25,7 @@ import android.net.Uri interface PermalinkParser { /** * Turns a uri string to a [PermalinkData]. - */ - fun parse(uriString: String): PermalinkData - - /** - * Turns a uri to a [PermalinkData]. * https://github.com/matrix-org/matrix-doc/blob/master/proposals/1704-matrix.to-permalinks.md */ - fun parse(uri: Uri): PermalinkData + fun parse(uriString: String): PermalinkData } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/Mention.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/Mention.kt index 47fd900a8f..5285638713 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/Mention.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/Mention.kt @@ -22,5 +22,6 @@ import io.element.android.libraries.matrix.api.core.UserId sealed interface Mention { data class User(val userId: UserId) : Mention data object AtRoom : Mention - data class Room(val roomId: RoomId?, val roomAlias: String?) : Mention + data class Room(val roomId: RoomId) : Mention + data class RoomAlias(val roomAlias: String?) : Mention } diff --git a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkDataTest.kt b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkDataTest.kt deleted file mode 100644 index 03a56651e8..0000000000 --- a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkDataTest.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.element.android.libraries.matrix.api.permalink - -import com.google.common.truth.Truth.assertThat -import kotlinx.collections.immutable.persistentListOf -import org.junit.Test - -class PermalinkDataTest { - @Test - fun `getRoomId() returns value when isRoomAlias is false`() { - val permalinkData = PermalinkData.RoomLink( - roomIdOrAlias = "!abcdef123456:matrix.org", - isRoomAlias = false, - eventId = null, - viaParameters = persistentListOf(), - ) - assertThat(permalinkData.getRoomId()).isNotNull() - assertThat(permalinkData.getRoomAlias()).isNull() - } - - @Test - fun `getRoomAlias() returns value when isRoomAlias is true`() { - val permalinkData = PermalinkData.RoomLink( - roomIdOrAlias = "#room:matrix.org", - isRoomAlias = true, - eventId = null, - viaParameters = persistentListOf(), - ) - assertThat(permalinkData.getRoomId()).isNull() - assertThat(permalinkData.getRoomAlias()).isNotNull() - } -} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParser.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParser.kt index ab91a89af9..7bf095a9f8 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParser.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParser.kt @@ -17,16 +17,17 @@ package io.element.android.libraries.matrix.impl.permalink import android.net.Uri -import android.net.UrlQuerySanitizer import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.di.AppScope -import io.element.android.libraries.matrix.api.core.MatrixPatterns +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.MatrixToConverter import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkParser import kotlinx.collections.immutable.toImmutableList -import timber.log.Timber -import java.net.URLDecoder +import org.matrix.rustcomponents.sdk.MatrixId +import org.matrix.rustcomponents.sdk.parseMatrixEntityFrom import javax.inject.Inject /** @@ -41,118 +42,45 @@ class DefaultPermalinkParser @Inject constructor( ) : PermalinkParser { /** * Turns a uri string to a [PermalinkData]. + * https://github.com/matrix-org/matrix-doc/blob/master/proposals/1704-matrix.to-permalinks.md */ override fun parse(uriString: String): PermalinkData { val uri = Uri.parse(uriString) - return parse(uri) - } - - /** - * Turns a uri to a [PermalinkData]. - * https://github.com/matrix-org/matrix-doc/blob/master/proposals/1704-matrix.to-permalinks.md - */ - override fun parse(uri: Uri): PermalinkData { // the client or element-based domain permalinks (e.g. https://app.element.io/#/user/@chagai95:matrix.org) don't have the // mxid in the first param (like matrix.to does - https://matrix.to/#/@chagai95:matrix.org) but rather in the second after /user/ so /user/mxid // so convert URI to matrix.to to simplify parsing process val matrixToUri = matrixToConverter.convert(uri) ?: return PermalinkData.FallbackLink(uri) - // We can't use uri.fragment as it is decoding to early and it will break the parsing - // of parameters that represents url (like signurl) - val fragment = matrixToUri.toString().substringAfter("#") // uri.fragment - if (fragment.isEmpty()) { - return PermalinkData.FallbackLink(uri) - } - val safeFragment = fragment.substringBefore('?') - val viaQueryParameters = fragment.getViaParameters() - - // we are limiting to 2 params - val params = safeFragment - .split(MatrixPatterns.SEP_REGEX) - .filter { it.isNotEmpty() } - .take(2) - - val decodedParams = params - .map { URLDecoder.decode(it, "UTF-8") } - - val identifier = params.getOrNull(0) - val decodedIdentifier = decodedParams.getOrNull(0) - val extraParameter = decodedParams.getOrNull(1) - return when { - identifier.isNullOrEmpty() || decodedIdentifier.isNullOrEmpty() -> PermalinkData.FallbackLink(uri) - MatrixPatterns.isUserId(decodedIdentifier) -> PermalinkData.UserLink(userId = decodedIdentifier) - MatrixPatterns.isRoomId(decodedIdentifier) -> { - handleRoomIdCase(fragment, decodedIdentifier, matrixToUri, extraParameter, viaQueryParameters) - } - MatrixPatterns.isRoomAlias(decodedIdentifier) -> { - PermalinkData.RoomLink( - roomIdOrAlias = decodedIdentifier, - isRoomAlias = true, - eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) }, - viaParameters = viaQueryParameters.toImmutableList() + val result = runCatching { + parseMatrixEntityFrom(matrixToUri.toString()) + }.getOrNull() + return if (result == null) { + PermalinkData.FallbackLink(uri) + } else { + val viaParameters = result.via.toImmutableList() + when (val id = result.id) { + is MatrixId.Room -> PermalinkData.RoomIdLink( + roomId = RoomId(id.id), + viaParameters = viaParameters, ) - } - else -> PermalinkData.FallbackLink(uri, MatrixPatterns.isGroupId(identifier)) - } - } - - private fun handleRoomIdCase(fragment: String, identifier: String, uri: Uri, extraParameter: String?, viaQueryParameters: List): PermalinkData { - // Can't rely on built in parsing because it's messing around the signurl - val paramList = safeExtractParams(fragment) - val signUrl = paramList.firstOrNull { it.first == "signurl" }?.second - val email = paramList.firstOrNull { it.first == "email" }?.second - return if (signUrl.isNullOrEmpty().not() && email.isNullOrEmpty().not()) { - try { - val signValidUri = Uri.parse(signUrl) - val identityServerHost = signValidUri.authority ?: throw IllegalArgumentException("missing `authority`") - val token = signValidUri.getQueryParameter("token") ?: throw IllegalArgumentException("missing `token`") - val privateKey = signValidUri.getQueryParameter("private_key") ?: throw IllegalArgumentException("missing `private_key`") - PermalinkData.RoomEmailInviteLink( - roomId = identifier, - email = email!!, - signUrl = signUrl!!, - roomName = paramList.firstOrNull { it.first == "room_name" }?.second, - inviterName = paramList.firstOrNull { it.first == "inviter_name" }?.second, - roomAvatarUrl = paramList.firstOrNull { it.first == "room_avatar_url" }?.second, - roomType = paramList.firstOrNull { it.first == "room_type" }?.second, - identityServer = identityServerHost, - token = token, - privateKey = privateKey + is MatrixId.User -> PermalinkData.UserLink( + userId = UserId(id.id), + ) + is MatrixId.RoomAlias -> PermalinkData.RoomAliasLink( + roomAlias = id.alias, + viaParameters = viaParameters, + ) + is MatrixId.EventOnRoomId -> PermalinkData.EventIdLink( + roomId = RoomId(id.roomId), + eventId = EventId(id.eventId), + viaParameters = viaParameters, + ) + is MatrixId.EventOnRoomAlias -> PermalinkData.EventIdAliasLink( + roomAlias = id.alias, + eventId = EventId(id.eventId), + viaParameters = viaParameters, ) - } catch (failure: Throwable) { - Timber.i("## Permalink: Failed to parse permalink $signUrl") - PermalinkData.FallbackLink(uri) - } - } else { - PermalinkData.RoomLink( - roomIdOrAlias = identifier, - isRoomAlias = false, - eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) }, - viaParameters = viaQueryParameters.toImmutableList() - ) - } - } - - private fun safeExtractParams(fragment: String) = - fragment.substringAfter("?").split('&').mapNotNull { - val splitNameValue = it.split("=") - if (splitNameValue.size == 2) { - Pair(splitNameValue[0], URLDecoder.decode(splitNameValue[1], "UTF-8")) - } else { - null } } - - private fun String.getViaParameters(): List { - return runCatching { - UrlQuerySanitizer(this) - .parameterList - .filter { - it.mParameter == "via" - } - .map { - URLDecoder.decode(it.mValue, "UTF-8") - } - }.getOrDefault(emptyList()) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParserTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParserTest.kt index 1e9e3bc2dc..af9043be72 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParserTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParserTest.kt @@ -17,6 +17,9 @@ package io.element.android.libraries.matrix.impl.permalink 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.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkData import kotlinx.collections.immutable.persistentListOf import org.junit.Test @@ -69,7 +72,7 @@ class DefaultPermalinkParserTest { val url = "https://app.element.io/#/user/@test:matrix.org" assertThat(sut.parse(url)).isEqualTo( PermalinkData.UserLink( - userId = "@test:matrix.org" + userId = UserId("@test:matrix.org") ) ) } @@ -81,10 +84,8 @@ class DefaultPermalinkParserTest { ) val url = "https://app.element.io/#/room/!aBCD1234:matrix.org" assertThat(sut.parse(url)).isEqualTo( - PermalinkData.RoomLink( - roomIdOrAlias = "!aBCD1234:matrix.org", - isRoomAlias = false, - eventId = null, + PermalinkData.RoomIdLink( + roomId = RoomId("!aBCD1234:matrix.org"), viaParameters = persistentListOf(), ) ) @@ -97,10 +98,9 @@ class DefaultPermalinkParserTest { ) val url = "https://app.element.io/#/room/!aBCD1234:matrix.org/$1234567890abcdef:matrix.org" assertThat(sut.parse(url)).isEqualTo( - PermalinkData.RoomLink( - roomIdOrAlias = "!aBCD1234:matrix.org", - isRoomAlias = false, - eventId = "\$1234567890abcdef:matrix.org", + PermalinkData.EventIdLink( + roomId = RoomId("!aBCD1234:matrix.org"), + eventId = EventId("$1234567890abcdef:matrix.org"), viaParameters = persistentListOf(), ) ) @@ -113,10 +113,8 @@ class DefaultPermalinkParserTest { ) val url = "https://app.element.io/#/room/!aBCD1234:matrix.org/1234567890abcdef:matrix.org" assertThat(sut.parse(url)).isEqualTo( - PermalinkData.RoomLink( - roomIdOrAlias = "!aBCD1234:matrix.org", - isRoomAlias = false, - eventId = null, + PermalinkData.RoomIdLink( + roomId = RoomId("!aBCD1234:matrix.org"), viaParameters = persistentListOf(), ) ) @@ -129,10 +127,9 @@ class DefaultPermalinkParserTest { ) val url = "https://app.element.io/#/room/!aBCD1234:matrix.org/$1234567890abcdef:matrix.org?via=matrix.org&via=matrix.com" assertThat(sut.parse(url)).isEqualTo( - PermalinkData.RoomLink( - roomIdOrAlias = "!aBCD1234:matrix.org", - isRoomAlias = false, - eventId = "\$1234567890abcdef:matrix.org", + PermalinkData.EventIdLink( + roomId = RoomId("!aBCD1234:matrix.org"), + eventId = EventId("$1234567890abcdef:matrix.org"), viaParameters = persistentListOf("matrix.org", "matrix.com"), ) ) @@ -145,10 +142,23 @@ class DefaultPermalinkParserTest { ) val url = "https://app.element.io/#/room/#element-android:matrix.org" assertThat(sut.parse(url)).isEqualTo( - PermalinkData.RoomLink( - roomIdOrAlias = "#element-android:matrix.org", - isRoomAlias = true, - eventId = null, + PermalinkData.RoomAliasLink( + roomAlias = "#element-android:matrix.org", + viaParameters = persistentListOf(), + ) + ) + } + + @Test + fun `parsing a valid room alias with eventId url returns a room link`() { + val sut = DefaultPermalinkParser( + matrixToConverter = DefaultMatrixToConverter(), + ) + val url = "https://app.element.io/#/room/#element-android:matrix.org/$1234567890abcdef:matrix.org" + assertThat(sut.parse(url)).isEqualTo( + PermalinkData.EventIdAliasLink( + roomAlias = "#element-android:matrix.org", + eventId = EventId("$1234567890abcdef:matrix.org"), viaParameters = persistentListOf(), ) ) @@ -188,7 +198,7 @@ class DefaultPermalinkParserTest { "&room_type=" assertThat(sut.parse(url)).isEqualTo( PermalinkData.RoomEmailInviteLink( - roomId = "!aBCDEF12345:matrix.org", + roomId = RoomId("!aBCDEF12345:matrix.org"), email = "testuser@element.io", signUrl = "https://vector.im/_matrix/identity/api/v1/sign-ed25519?token=a_token&private_key=a_private_key", roomName = "TestRoom", diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkParser.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkParser.kt index f046eadf93..d1ffb70f99 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkParser.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/permalink/FakePermalinkParser.kt @@ -16,7 +16,6 @@ package io.element.android.libraries.matrix.test.permalink -import android.net.Uri import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkParser @@ -30,8 +29,4 @@ class FakePermalinkParser( override fun parse(uriString: String): PermalinkData { return result() } - - override fun parse(uri: Uri): PermalinkData { - TODO("Not yet implemented") - } } diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrixui/messages/ToHtmlDocumentTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrixui/messages/ToHtmlDocumentTest.kt index ab83f77e66..9dee206339 100644 --- a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrixui/messages/ToHtmlDocumentTest.kt +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrixui/messages/ToHtmlDocumentTest.kt @@ -18,6 +18,7 @@ package io.element.android.libraries.matrixui.messages import android.net.Uri import com.google.common.truth.Truth.assertThat +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.permalink.PermalinkParser import io.element.android.libraries.matrix.api.timeline.item.event.FormattedBody @@ -78,10 +79,8 @@ class ToHtmlDocumentTest { val document = body.toHtmlDocument(permalinkParser = object : PermalinkParser { override fun parse(uriString: String): PermalinkData { - return PermalinkData.UserLink("@alice:matrix.org") + return PermalinkData.UserLink(UserId("@alice:matrix.org")) } - - override fun parse(uri: Uri): PermalinkData = TODO("Not yet implemented") }) assertThat(document?.text()).isEqualTo("Hey @Alice!") } @@ -95,10 +94,8 @@ class ToHtmlDocumentTest { val document = body.toHtmlDocument(permalinkParser = object : PermalinkParser { override fun parse(uriString: String): PermalinkData { - return PermalinkData.UserLink("@alice:matrix.org") + return PermalinkData.UserLink(UserId("@alice:matrix.org")) } - - override fun parse(uri: Uri): PermalinkData = TODO("Not yet implemented") }) assertThat(document?.text()).isEqualTo("Hey @Alice!") } @@ -114,8 +111,6 @@ class ToHtmlDocumentTest { override fun parse(uriString: String): PermalinkData { return PermalinkData.FallbackLink(uri = Uri.parse("https://matrix.org")) } - - override fun parse(uri: Uri): PermalinkData = TODO("Not yet implemented") }) assertThat(document?.text()).isEqualTo("Hey Alice!") } diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index 2ac322827c..0fea92a014 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -914,7 +914,6 @@ private fun ATextComposer( voiceMessageState = voiceMessageState, permalinkParser = object : PermalinkParser { override fun parse(uriString: String): PermalinkData = TODO("Not yet implemented") - override fun parse(uri: Uri): PermalinkData = TODO("Not yet implemented") }, composerMode = composerMode, enableTextFormatting = enableTextFormatting, diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpanProvider.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpanProvider.kt index e50b0fc16a..4d705983ff 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpanProvider.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpanProvider.kt @@ -18,7 +18,6 @@ package io.element.android.libraries.textcomposer.mentions import android.graphics.Color import android.graphics.Typeface -import android.net.Uri import android.view.ViewGroup import android.widget.TextView import androidx.compose.foundation.layout.PaddingValues @@ -41,6 +40,7 @@ import io.element.android.libraries.designsystem.theme.currentUserMentionPillTex import io.element.android.libraries.designsystem.theme.mentionPillBackground import io.element.android.libraries.designsystem.theme.mentionPillText 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.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkParser import kotlinx.collections.immutable.persistentListOf @@ -80,7 +80,7 @@ class MentionSpanProvider( val (startPaddingPx, endPaddingPx) = paddingValuesPx.value return when { permalinkData is PermalinkData.UserLink -> { - val isCurrentUser = permalinkData.userId == currentSessionId.value + val isCurrentUser = permalinkData.userId == currentSessionId MentionSpan( type = MentionSpan.Type.USER, backgroundColor = if (isCurrentUser) currentUserBackgroundColor else otherBackgroundColor, @@ -137,19 +137,15 @@ internal fun MentionSpanPreview() { permalinkParser = object : PermalinkParser { override fun parse(uriString: String): PermalinkData { return when (uriString) { - "https://matrix.to/#/@me:matrix.org" -> PermalinkData.UserLink("@me:matrix.org") - "https://matrix.to/#/@other:matrix.org" -> PermalinkData.UserLink("@other:matrix.org") - "https://matrix.to/#/#room:matrix.org" -> PermalinkData.RoomLink( - roomIdOrAlias = "#room:matrix.org", - isRoomAlias = true, - eventId = null, + "https://matrix.to/#/@me:matrix.org" -> PermalinkData.UserLink(UserId("@me:matrix.org")) + "https://matrix.to/#/@other:matrix.org" -> PermalinkData.UserLink(UserId("@other:matrix.org")) + "https://matrix.to/#/#room:matrix.org" -> PermalinkData.RoomAliasLink( + roomAlias = "#room:matrix.org", viaParameters = persistentListOf(), ) else -> TODO() } } - - override fun parse(uri: Uri): PermalinkData = TODO() }, ) ElementPreview { diff --git a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/MentionSpanProviderTest.kt b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/MentionSpanProviderTest.kt index 475b879895..a5f31718cd 100644 --- a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/MentionSpanProviderTest.kt +++ b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/mentions/MentionSpanProviderTest.kt @@ -18,6 +18,7 @@ package io.element.android.libraries.textcomposer.impl.mentions import android.graphics.Color import com.google.common.truth.Truth.assertThat +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_SESSION_ID import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser @@ -50,7 +51,7 @@ class MentionSpanProviderTest { @Test fun `getting mention span for current user should return a MentionSpan with custom colors`() { - permalinkParser.givenResult(PermalinkData.UserLink(currentUserId.value)) + permalinkParser.givenResult(PermalinkData.UserLink(currentUserId)) val mentionSpan = mentionSpanProvider.getMentionSpanFor("@me:matrix.org", "https://matrix.to/#/${currentUserId.value}") assertThat(mentionSpan.backgroundColor).isEqualTo(myUserColor) assertThat(mentionSpan.textColor).isEqualTo(myUserColor) @@ -58,7 +59,7 @@ class MentionSpanProviderTest { @Test fun `getting mention span for other user should return a MentionSpan with normal colors`() { - permalinkParser.givenResult(PermalinkData.UserLink("@other:matrix.org")) + permalinkParser.givenResult(PermalinkData.UserLink(UserId("@other:matrix.org"))) val mentionSpan = mentionSpanProvider.getMentionSpanFor("@other:matrix.org", "https://matrix.to/#/@other:matrix.org") assertThat(mentionSpan.backgroundColor).isEqualTo(otherColor) assertThat(mentionSpan.textColor).isEqualTo(otherColor) @@ -67,10 +68,8 @@ class MentionSpanProviderTest { @Test fun `getting mention span for a room should return a MentionSpan with normal colors`() { permalinkParser.givenResult( - PermalinkData.RoomLink( - roomIdOrAlias = "#room:matrix.org", - isRoomAlias = true, - eventId = null, + PermalinkData.RoomAliasLink( + roomAlias = "#room:matrix.org", viaParameters = persistentListOf(), ) ) @@ -82,10 +81,8 @@ class MentionSpanProviderTest { @Test fun `getting mention span for @room should return a MentionSpan with normal colors`() { permalinkParser.givenResult( - PermalinkData.RoomLink( - roomIdOrAlias = "#", - isRoomAlias = true, - eventId = null, + PermalinkData.RoomAliasLink( + roomAlias = "#", viaParameters = persistentListOf(), ) ) diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/OnlyFallbackPermalinkParser.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/OnlyFallbackPermalinkParser.kt index 50903a910d..9825f29268 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/OnlyFallbackPermalinkParser.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/OnlyFallbackPermalinkParser.kt @@ -24,8 +24,4 @@ class OnlyFallbackPermalinkParser : PermalinkParser { override fun parse(uriString: String): PermalinkData { return PermalinkData.FallbackLink(Uri.parse(uriString)) } - - override fun parse(uri: Uri): PermalinkData { - return PermalinkData.FallbackLink(uri) - } } From 83a49a88a552ff34e0ff29f543ac91e8b86f9e62 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 17:51:51 +0200 Subject: [PATCH 49/52] changelog --- changelog.d/2709.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/2709.misc diff --git a/changelog.d/2709.misc b/changelog.d/2709.misc new file mode 100644 index 0000000000..96328571cc --- /dev/null +++ b/changelog.d/2709.misc @@ -0,0 +1 @@ + Parse permalink using parseMatrixEntityFrom from the SDK From 9ee36e9ca4dc15c19b2daa3bec996b2c96054c7f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Apr 2024 17:57:15 +0200 Subject: [PATCH 50/52] Remove unnecessary tests. --- .../permalink/DefaultPermalinkParserTest.kt | 214 ------------------ 1 file changed, 214 deletions(-) delete mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParserTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParserTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParserTest.kt deleted file mode 100644 index af9043be72..0000000000 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/permalink/DefaultPermalinkParserTest.kt +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2024 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.element.android.libraries.matrix.impl.permalink - -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.UserId -import io.element.android.libraries.matrix.api.permalink.PermalinkData -import kotlinx.collections.immutable.persistentListOf -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner - -@RunWith(RobolectricTestRunner::class) -class DefaultPermalinkParserTest { - @Test - fun `parsing an invalid url returns a fallback link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://element.io" - assertThat(sut.parse(url)).isInstanceOf(PermalinkData.FallbackLink::class.java) - } - - @Test - fun `parsing an invalid url with the right path but no content returns a fallback link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/user" - assertThat(sut.parse(url)).isInstanceOf(PermalinkData.FallbackLink::class.java) - } - - @Test - fun `parsing an invalid url with the right path but empty content returns a fallback link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/user/" - assertThat(sut.parse(url)).isInstanceOf(PermalinkData.FallbackLink::class.java) - } - - @Test - fun `parsing an invalid url with the right path but invalid content returns a fallback link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/user/some%20user!" - assertThat(sut.parse(url)).isInstanceOf(PermalinkData.FallbackLink::class.java) - } - - @Test - fun `parsing a valid user url returns a user link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/user/@test:matrix.org" - assertThat(sut.parse(url)).isEqualTo( - PermalinkData.UserLink( - userId = UserId("@test:matrix.org") - ) - ) - } - - @Test - fun `parsing a valid room id url returns a room link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/room/!aBCD1234:matrix.org" - assertThat(sut.parse(url)).isEqualTo( - PermalinkData.RoomIdLink( - roomId = RoomId("!aBCD1234:matrix.org"), - viaParameters = persistentListOf(), - ) - ) - } - - @Test - fun `parsing a valid room id with event id url returns a room link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/room/!aBCD1234:matrix.org/$1234567890abcdef:matrix.org" - assertThat(sut.parse(url)).isEqualTo( - PermalinkData.EventIdLink( - roomId = RoomId("!aBCD1234:matrix.org"), - eventId = EventId("$1234567890abcdef:matrix.org"), - viaParameters = persistentListOf(), - ) - ) - } - - @Test - fun `parsing a valid room id with and invalid event id url returns a room link with no event id`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/room/!aBCD1234:matrix.org/1234567890abcdef:matrix.org" - assertThat(sut.parse(url)).isEqualTo( - PermalinkData.RoomIdLink( - roomId = RoomId("!aBCD1234:matrix.org"), - viaParameters = persistentListOf(), - ) - ) - } - - @Test - fun `parsing a valid room id with event id and via parameters url returns a room link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/room/!aBCD1234:matrix.org/$1234567890abcdef:matrix.org?via=matrix.org&via=matrix.com" - assertThat(sut.parse(url)).isEqualTo( - PermalinkData.EventIdLink( - roomId = RoomId("!aBCD1234:matrix.org"), - eventId = EventId("$1234567890abcdef:matrix.org"), - viaParameters = persistentListOf("matrix.org", "matrix.com"), - ) - ) - } - - @Test - fun `parsing a valid room alias url returns a room link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/room/#element-android:matrix.org" - assertThat(sut.parse(url)).isEqualTo( - PermalinkData.RoomAliasLink( - roomAlias = "#element-android:matrix.org", - viaParameters = persistentListOf(), - ) - ) - } - - @Test - fun `parsing a valid room alias with eventId url returns a room link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/room/#element-android:matrix.org/$1234567890abcdef:matrix.org" - assertThat(sut.parse(url)).isEqualTo( - PermalinkData.EventIdAliasLink( - roomAlias = "#element-android:matrix.org", - eventId = EventId("$1234567890abcdef:matrix.org"), - viaParameters = persistentListOf(), - ) - ) - } - - @Test - fun `parsing a url with an invalid signurl returns a fallback link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - // This url has no private key - val url = "https://app.element.io/#/room/%21aBCDEF12345%3Amatrix.org" + - "?email=testuser%40element.io" + - "&signurl=https%3A%2F%2Fvector.im%2F_matrix%2Fidentity%2Fapi%2Fv1%2Fsign-ed25519%3Ftoken%3Da_token" + - "&room_name=TestRoom" + - "&room_avatar_url=" + - "&inviter_name=User" + - "&guest_access_token=" + - "&guest_user_id=" + - "&room_type=" - assertThat(sut.parse(url)).isInstanceOf(PermalinkData.FallbackLink::class.java) - } - - @Test - fun `parsing a url with signurl returns a room email invite link`() { - val sut = DefaultPermalinkParser( - matrixToConverter = DefaultMatrixToConverter(), - ) - val url = "https://app.element.io/#/room/%21aBCDEF12345%3Amatrix.org" + - "?email=testuser%40element.io" + - "&signurl=https%3A%2F%2Fvector.im%2F_matrix%2Fidentity%2Fapi%2Fv1%2Fsign-ed25519%3Ftoken%3Da_token%26private_key%3Da_private_key" + - "&room_name=TestRoom" + - "&room_avatar_url=" + - "&inviter_name=User" + - "&guest_access_token=" + - "&guest_user_id=" + - "&room_type=" - assertThat(sut.parse(url)).isEqualTo( - PermalinkData.RoomEmailInviteLink( - roomId = RoomId("!aBCDEF12345:matrix.org"), - email = "testuser@element.io", - signUrl = "https://vector.im/_matrix/identity/api/v1/sign-ed25519?token=a_token&private_key=a_private_key", - roomName = "TestRoom", - roomAvatarUrl = "", - inviterName = "User", - identityServer = "vector.im", - token = "a_token", - privateKey = "a_private_key", - roomType = "", - ) - ) - } -} From e838e7aa3b7f6af02e01c6caf6de122ff68352ba Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 17 Apr 2024 08:23:45 +0200 Subject: [PATCH 51/52] Changelog for version 0.4.10 --- CHANGES.md | 17 +++++++++++++++++ changelog.d/2698.misc | 1 - changelog.d/2703.misc | 1 - changelog.d/2708.misc | 1 - changelog.d/2709.misc | 1 - 5 files changed, 17 insertions(+), 4 deletions(-) delete mode 100644 changelog.d/2698.misc delete mode 100644 changelog.d/2703.misc delete mode 100644 changelog.d/2708.misc delete mode 100644 changelog.d/2709.misc diff --git a/CHANGES.md b/CHANGES.md index 72c9a9cf65..38cb6e72cc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,20 @@ +Changes in Element X v0.4.10 (2024-04-17) +========================================= + +Matrix Rust SDK 0.2.14 + +Features ✨ +---------- + - Rework room navigation to handle unknown room and prepare work on permalink. ([#2695](https://github.com/element-hq/element-x-android/issues/2695)) + +Other changes +------------- + - Encrypt new session data with a passphrase ([#2703](https://github.com/element-hq/element-x-android/issues/2703)) + - Use sdk API to build permalinks ([#2708](https://github.com/element-hq/element-x-android/issues/2708)) + - Parse permalink using parseMatrixEntityFrom from the SDK ([#2709](https://github.com/element-hq/element-x-android/issues/2709)) + - Fix compile for forks that use the `noop` analytics module ([#2698](https://github.com/element-hq/element-x-android/issues/2698)) + + Changes in Element X v0.4.9 (2024-04-12) ======================================== diff --git a/changelog.d/2698.misc b/changelog.d/2698.misc deleted file mode 100644 index a15fdd9f7a..0000000000 --- a/changelog.d/2698.misc +++ /dev/null @@ -1 +0,0 @@ -Fix compile for forks that use the `noop` analytics module diff --git a/changelog.d/2703.misc b/changelog.d/2703.misc deleted file mode 100644 index 06d354f25e..0000000000 --- a/changelog.d/2703.misc +++ /dev/null @@ -1 +0,0 @@ -Encrypt new session data with a passphrase diff --git a/changelog.d/2708.misc b/changelog.d/2708.misc deleted file mode 100644 index 807824f3ab..0000000000 --- a/changelog.d/2708.misc +++ /dev/null @@ -1 +0,0 @@ - Use sdk API to build permalinks diff --git a/changelog.d/2709.misc b/changelog.d/2709.misc deleted file mode 100644 index 96328571cc..0000000000 --- a/changelog.d/2709.misc +++ /dev/null @@ -1 +0,0 @@ - Parse permalink using parseMatrixEntityFrom from the SDK From 282c345b3cae2f5280c8de1b3fe65fc37314ec54 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 17 Apr 2024 08:24:30 +0200 Subject: [PATCH 52/52] Adding fastlane file for version 0.4.10 --- fastlane/metadata/android/en-US/changelogs/40004100.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40004100.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40004100.txt b/fastlane/metadata/android/en-US/changelogs/40004100.txt new file mode 100644 index 0000000000..1618e5e9ee --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40004100.txt @@ -0,0 +1,2 @@ +Main changes in this version: Prepare navigation with permalink. +Full changelog: https://github.com/element-hq/element-x-android/releases