Browse Source

Merge pull request #3360 from element-hq/feature/bma/sessionVerificationBannerIsBack

Add banner entry point to set up recovery
pull/3376/head
Benoit Marty 3 weeks ago committed by GitHub
parent
commit
31d0621fa1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt
  2. 1
      features/roomlist/api/src/main/kotlin/io/element/android/features/roomlist/api/RoomListEntryPoint.kt
  3. 5
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListNode.kt
  4. 11
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt
  5. 1
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt
  6. 1
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt
  7. 5
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt
  8. 38
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt
  9. 49
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/SetUpRecoveryKeyBanner.kt
  10. 2
      features/roomlist/impl/src/main/res/values/localazy.xml
  11. 13
      features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt
  12. 41
      features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListViewTest.kt
  13. 3
      features/securebackup/api/src/main/kotlin/io/element/android/features/securebackup/api/SecureBackupEntryPoint.kt
  14. 1
      features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt
  15. 1
      samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt
  16. 3
      tests/uitests/src/test/snapshots/images/features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_en.png
  17. 3
      tests/uitests/src/test/snapshots/images/features.roomlist.impl.components_SetUpRecoveryKeyBanner_Night_0_en.png
  18. 3
      tests/uitests/src/test/snapshots/images/features.roomlist.impl_RoomListView_Day_11_en.png
  19. 3
      tests/uitests/src/test/snapshots/images/features.roomlist.impl_RoomListView_Night_11_en.png
  20. 1
      tools/localazy/config.json

4
appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt

@ -259,6 +259,10 @@ class LoggedInFlowNode @AssistedInject constructor(
backstack.push(NavTarget.CreateRoom) backstack.push(NavTarget.CreateRoom)
} }
override fun onSetUpRecoveryClick() {
backstack.push(NavTarget.SecureBackup(initialElement = SecureBackupEntryPoint.InitialTarget.SetUpRecovery))
}
override fun onSessionConfirmRecoveryKeyClick() { override fun onSessionConfirmRecoveryKeyClick() {
backstack.push(NavTarget.SecureBackup(initialElement = SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey)) backstack.push(NavTarget.SecureBackup(initialElement = SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey))
} }

1
features/roomlist/api/src/main/kotlin/io/element/android/features/roomlist/api/RoomListEntryPoint.kt

@ -33,6 +33,7 @@ interface RoomListEntryPoint : FeatureEntryPoint {
fun onRoomClick(roomId: RoomId) fun onRoomClick(roomId: RoomId)
fun onCreateRoomClick() fun onCreateRoomClick()
fun onSettingsClick() fun onSettingsClick()
fun onSetUpRecoveryClick()
fun onSessionConfirmRecoveryKeyClick() fun onSessionConfirmRecoveryKeyClick()
fun onRoomSettingsClick(roomId: RoomId) fun onRoomSettingsClick(roomId: RoomId)
fun onReportBugClick() fun onReportBugClick()

5
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListNode.kt

@ -66,6 +66,10 @@ class RoomListNode @AssistedInject constructor(
plugins<RoomListEntryPoint.Callback>().forEach { it.onCreateRoomClick() } plugins<RoomListEntryPoint.Callback>().forEach { it.onCreateRoomClick() }
} }
private fun onSetUpRecoveryClick() {
plugins<RoomListEntryPoint.Callback>().forEach { it.onSetUpRecoveryClick() }
}
private fun onSessionConfirmRecoveryKeyClick() { private fun onSessionConfirmRecoveryKeyClick() {
plugins<RoomListEntryPoint.Callback>().forEach { it.onSessionConfirmRecoveryKeyClick() } plugins<RoomListEntryPoint.Callback>().forEach { it.onSessionConfirmRecoveryKeyClick() }
} }
@ -98,6 +102,7 @@ class RoomListNode @AssistedInject constructor(
onRoomClick = this::onRoomClick, onRoomClick = this::onRoomClick,
onSettingsClick = this::onOpenSettings, onSettingsClick = this::onOpenSettings,
onCreateRoomClick = this::onCreateRoomClick, onCreateRoomClick = this::onCreateRoomClick,
onSetUpRecoveryClick = this::onSetUpRecoveryClick,
onConfirmRecoveryKeyClick = this::onSessionConfirmRecoveryKeyClick, onConfirmRecoveryKeyClick = this::onSessionConfirmRecoveryKeyClick,
onRoomSettingsClick = this::onRoomSettingsClick, onRoomSettingsClick = this::onRoomSettingsClick,
onMenuActionClick = { onMenuActionClick(activity, it) }, onMenuActionClick = { onMenuActionClick(activity, it) },

11
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt

@ -187,8 +187,15 @@ class RoomListPresenter @Inject constructor(
derivedStateOf { derivedStateOf {
when { when {
currentSecurityBannerDismissed -> SecurityBannerState.None currentSecurityBannerDismissed -> SecurityBannerState.None
recoveryState == RecoveryState.INCOMPLETE && syncState == SyncState.Running -> {
syncState == SyncState.Running -> SecurityBannerState.RecoveryKeyConfirmation when (recoveryState) {
RecoveryState.UNKNOWN,
RecoveryState.DISABLED -> SecurityBannerState.SetUpRecovery
RecoveryState.INCOMPLETE -> SecurityBannerState.RecoveryKeyConfirmation
RecoveryState.WAITING_FOR_SYNC,
RecoveryState.ENABLED -> SecurityBannerState.None
}
}
else -> SecurityBannerState.None else -> SecurityBannerState.None
} }
} }

1
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt

@ -66,6 +66,7 @@ enum class InvitesState {
enum class SecurityBannerState { enum class SecurityBannerState {
None, None,
SetUpRecovery,
RecoveryKeyConfirmation, RecoveryKeyConfirmation,
} }

1
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt

@ -52,6 +52,7 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
aRoomListState(contentState = aSkeletonContentState()), aRoomListState(contentState = aSkeletonContentState()),
aRoomListState(matrixUser = MatrixUser(userId = UserId("@id:domain")), contentState = aMigrationContentState()), aRoomListState(matrixUser = MatrixUser(userId = UserId("@id:domain")), contentState = aMigrationContentState()),
aRoomListState(searchState = aRoomListSearchState(isSearchActive = true, query = "Test")), aRoomListState(searchState = aRoomListSearchState(isSearchActive = true, query = "Test")),
aRoomListState(contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SetUpRecovery)),
) )
} }

5
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt

@ -53,6 +53,7 @@ fun RoomListView(
state: RoomListState, state: RoomListState,
onRoomClick: (RoomId) -> Unit, onRoomClick: (RoomId) -> Unit,
onSettingsClick: () -> Unit, onSettingsClick: () -> Unit,
onSetUpRecoveryClick: () -> Unit,
onConfirmRecoveryKeyClick: () -> Unit, onConfirmRecoveryKeyClick: () -> Unit,
onCreateRoomClick: () -> Unit, onCreateRoomClick: () -> Unit,
onRoomSettingsClick: (roomId: RoomId) -> Unit, onRoomSettingsClick: (roomId: RoomId) -> Unit,
@ -78,6 +79,7 @@ fun RoomListView(
RoomListScaffold( RoomListScaffold(
state = state, state = state,
onSetUpRecoveryClick = onSetUpRecoveryClick,
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
onRoomClick = onRoomClick, onRoomClick = onRoomClick,
onOpenSettings = onSettingsClick, onOpenSettings = onSettingsClick,
@ -106,6 +108,7 @@ fun RoomListView(
@Composable @Composable
private fun RoomListScaffold( private fun RoomListScaffold(
state: RoomListState, state: RoomListState,
onSetUpRecoveryClick: () -> Unit,
onConfirmRecoveryKeyClick: () -> Unit, onConfirmRecoveryKeyClick: () -> Unit,
onRoomClick: (RoomId) -> Unit, onRoomClick: (RoomId) -> Unit,
onOpenSettings: () -> Unit, onOpenSettings: () -> Unit,
@ -142,6 +145,7 @@ private fun RoomListScaffold(
contentState = state.contentState, contentState = state.contentState,
filtersState = state.filtersState, filtersState = state.filtersState,
eventSink = state.eventSink, eventSink = state.eventSink,
onSetUpRecoveryClick = onSetUpRecoveryClick,
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
onRoomClick = ::onRoomClick, onRoomClick = ::onRoomClick,
onCreateRoomClick = onCreateRoomClick, onCreateRoomClick = onCreateRoomClick,
@ -178,6 +182,7 @@ internal fun RoomListViewPreview(@PreviewParameter(RoomListStateProvider::class)
state = state, state = state,
onRoomClick = {}, onRoomClick = {},
onSettingsClick = {}, onSettingsClick = {},
onSetUpRecoveryClick = {},
onConfirmRecoveryKeyClick = {}, onConfirmRecoveryKeyClick = {},
onCreateRoomClick = {}, onCreateRoomClick = {},
onRoomSettingsClick = {}, onRoomSettingsClick = {},

38
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt

@ -70,6 +70,7 @@ fun RoomListContentView(
contentState: RoomListContentState, contentState: RoomListContentState,
filtersState: RoomListFiltersState, filtersState: RoomListFiltersState,
eventSink: (RoomListEvents) -> Unit, eventSink: (RoomListEvents) -> Unit,
onSetUpRecoveryClick: () -> Unit,
onConfirmRecoveryKeyClick: () -> Unit, onConfirmRecoveryKeyClick: () -> Unit,
onRoomClick: (RoomListRoomSummary) -> Unit, onRoomClick: (RoomListRoomSummary) -> Unit,
onCreateRoomClick: () -> Unit, onCreateRoomClick: () -> Unit,
@ -95,6 +96,7 @@ fun RoomListContentView(
state = contentState, state = contentState,
filtersState = filtersState, filtersState = filtersState,
eventSink = eventSink, eventSink = eventSink,
onSetUpRecoveryClick = onSetUpRecoveryClick,
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
onRoomClick = onRoomClick, onRoomClick = onRoomClick,
) )
@ -141,6 +143,7 @@ private fun RoomsView(
state: RoomListContentState.Rooms, state: RoomListContentState.Rooms,
filtersState: RoomListFiltersState, filtersState: RoomListFiltersState,
eventSink: (RoomListEvents) -> Unit, eventSink: (RoomListEvents) -> Unit,
onSetUpRecoveryClick: () -> Unit,
onConfirmRecoveryKeyClick: () -> Unit, onConfirmRecoveryKeyClick: () -> Unit,
onRoomClick: (RoomListRoomSummary) -> Unit, onRoomClick: (RoomListRoomSummary) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -154,6 +157,7 @@ private fun RoomsView(
RoomsViewList( RoomsViewList(
state = state, state = state,
eventSink = eventSink, eventSink = eventSink,
onSetUpRecoveryClick = onSetUpRecoveryClick,
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
onRoomClick = onRoomClick, onRoomClick = onRoomClick,
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
@ -165,6 +169,7 @@ private fun RoomsView(
private fun RoomsViewList( private fun RoomsViewList(
state: RoomListContentState.Rooms, state: RoomListContentState.Rooms,
eventSink: (RoomListEvents) -> Unit, eventSink: (RoomListEvents) -> Unit,
onSetUpRecoveryClick: () -> Unit,
onConfirmRecoveryKeyClick: () -> Unit, onConfirmRecoveryKeyClick: () -> Unit,
onRoomClick: (RoomListRoomSummary) -> Unit, onRoomClick: (RoomListRoomSummary) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -188,21 +193,27 @@ private fun RoomsViewList(
// FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80 // FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80
contentPadding = PaddingValues(bottom = 80.dp) contentPadding = PaddingValues(bottom = 80.dp)
) { ) {
if (state.securityBannerState != SecurityBannerState.None) { when (state.securityBannerState) {
when (state.securityBannerState) { SecurityBannerState.SetUpRecovery -> {
SecurityBannerState.RecoveryKeyConfirmation -> { item {
item { SetUpRecoveryKeyBanner(
ConfirmRecoveryKeyBanner( onContinueClick = onSetUpRecoveryClick,
onContinueClick = onConfirmRecoveryKeyClick, onDismissClick = { updatedEventSink(RoomListEvents.DismissRecoveryKeyPrompt) }
onDismissClick = { updatedEventSink(RoomListEvents.DismissRecoveryKeyPrompt) } )
)
}
} }
else -> Unit
} }
} else if (state.fullScreenIntentPermissionsState.shouldDisplayBanner) { SecurityBannerState.RecoveryKeyConfirmation -> {
item { item {
FullScreenIntentPermissionBanner(state = state.fullScreenIntentPermissionsState) ConfirmRecoveryKeyBanner(
onContinueClick = onConfirmRecoveryKeyClick,
onDismissClick = { updatedEventSink(RoomListEvents.DismissRecoveryKeyPrompt) }
)
}
}
SecurityBannerState.None -> if (state.fullScreenIntentPermissionsState.shouldDisplayBanner) {
item {
FullScreenIntentPermissionBanner(state = state.fullScreenIntentPermissionsState)
}
} }
} }
@ -276,6 +287,7 @@ internal fun RoomListContentViewPreview(@PreviewParameter(RoomListContentStatePr
filterSelectionStates = RoomListFilter.entries.map { FilterSelectionState(it, isSelected = true) } filterSelectionStates = RoomListFilter.entries.map { FilterSelectionState(it, isSelected = true) }
), ),
eventSink = {}, eventSink = {},
onSetUpRecoveryClick = {},
onConfirmRecoveryKeyClick = {}, onConfirmRecoveryKeyClick = {},
onRoomClick = {}, onRoomClick = {},
onCreateRoomClick = {}, onCreateRoomClick = {},

49
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/SetUpRecoveryKeyBanner.kt

@ -0,0 +1,49 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.roomlist.impl.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import io.element.android.features.roomlist.impl.R
import io.element.android.libraries.designsystem.atomic.molecules.DialogLikeBannerMolecule
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
@Composable
internal fun SetUpRecoveryKeyBanner(
onContinueClick: () -> Unit,
onDismissClick: () -> Unit,
modifier: Modifier = Modifier,
) {
DialogLikeBannerMolecule(
modifier = modifier,
title = stringResource(R.string.banner_set_up_recovery_title),
content = stringResource(R.string.banner_set_up_recovery_content),
onSubmitClick = onContinueClick,
onDismissClick = onDismissClick,
)
}
@PreviewsDayNight
@Composable
internal fun SetUpRecoveryKeyBannerPreview() = ElementPreview {
SetUpRecoveryKeyBanner(
onContinueClick = {},
onDismissClick = {},
)
}

2
features/roomlist/impl/src/main/res/values/localazy.xml

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_set_up_recovery_content">"Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."</string>
<string name="banner_set_up_recovery_title">"Set up recovery"</string>
<string name="confirm_recovery_key_banner_message">"Your chat backup is currently out of sync. You need to enter your recovery key to maintain access to your chat backup."</string> <string name="confirm_recovery_key_banner_message">"Your chat backup is currently out of sync. You need to enter your recovery key to maintain access to your chat backup."</string>
<string name="confirm_recovery_key_banner_title">"Enter your recovery key"</string> <string name="confirm_recovery_key_banner_title">"Enter your recovery key"</string>
<string name="full_screen_intent_banner_message">"To ensure you never miss an important call, please change your settings to allow full-screen notifications when your phone is locked."</string> <string name="full_screen_intent_banner_message">"To ensure you never miss an important call, please change your settings to allow full-screen notifications when your phone is locked."</string>

13
features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt

@ -264,10 +264,21 @@ class RoomListPresenterTest {
val initialState = consumeItemsUntilPredicate { val initialState = consumeItemsUntilPredicate {
it.contentState is RoomListContentState.Rooms it.contentState is RoomListContentState.Rooms
}.last() }.last()
assertThat(initialState.contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.None) assertThat(initialState.contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.SetUpRecovery)
encryptionService.emitRecoveryState(RecoveryState.INCOMPLETE) encryptionService.emitRecoveryState(RecoveryState.INCOMPLETE)
val nextState = awaitItem() val nextState = awaitItem()
assertThat(nextState.contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.RecoveryKeyConfirmation) assertThat(nextState.contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.RecoveryKeyConfirmation)
// Also check other states
encryptionService.emitRecoveryState(RecoveryState.DISABLED)
assertThat(awaitItem().contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.SetUpRecovery)
encryptionService.emitRecoveryState(RecoveryState.WAITING_FOR_SYNC)
assertThat(awaitItem().contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.None)
encryptionService.emitRecoveryState(RecoveryState.DISABLED)
assertThat(awaitItem().contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.SetUpRecovery)
encryptionService.emitRecoveryState(RecoveryState.ENABLED)
assertThat(awaitItem().contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.None)
encryptionService.emitRecoveryState(RecoveryState.DISABLED)
assertThat(awaitItem().contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.SetUpRecovery)
nextState.eventSink(RoomListEvents.DismissRecoveryKeyPrompt) nextState.eventSink(RoomListEvents.DismissRecoveryKeyPrompt)
val finalState = awaitItem() val finalState = awaitItem()
assertThat(finalState.contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.None) assertThat(finalState.contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.None)

41
features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListViewTest.kt

@ -80,6 +80,24 @@ class RoomListViewTest {
eventsRecorder.assertSingle(RoomListEvents.DismissRecoveryKeyPrompt) eventsRecorder.assertSingle(RoomListEvents.DismissRecoveryKeyPrompt)
} }
@Test
fun `clicking on close setup key banner emits the expected Event`() {
val eventsRecorder = EventsRecorder<RoomListEvents>()
rule.setRoomListView(
state = aRoomListState(
contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SetUpRecovery),
eventSink = eventsRecorder,
)
)
// Remove automatic initial events
eventsRecorder.clear()
val close = rule.activity.getString(CommonStrings.action_close)
rule.onNodeWithContentDescription(close).performClick()
eventsRecorder.assertSingle(RoomListEvents.DismissRecoveryKeyPrompt)
}
@Test @Test
fun `clicking on continue recovery key banner invokes the expected callback`() { fun `clicking on continue recovery key banner invokes the expected callback`() {
val eventsRecorder = EventsRecorder<RoomListEvents>() val eventsRecorder = EventsRecorder<RoomListEvents>()
@ -101,6 +119,27 @@ class RoomListViewTest {
} }
} }
@Test
fun `clicking on continue setup key banner invokes the expected callback`() {
val eventsRecorder = EventsRecorder<RoomListEvents>()
ensureCalledOnce { callback ->
rule.setRoomListView(
state = aRoomListState(
contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SetUpRecovery),
eventSink = eventsRecorder,
),
onSetUpRecoveryClick = callback,
)
// Remove automatic initial events
eventsRecorder.clear()
rule.clickOn(CommonStrings.action_continue)
eventsRecorder.assertEmpty()
}
}
@Test @Test
fun `clicking on start chat when the session has no room invokes the expected callback`() { fun `clicking on start chat when the session has no room invokes the expected callback`() {
val eventsRecorder = EventsRecorder<RoomListEvents>(expectEvents = false) val eventsRecorder = EventsRecorder<RoomListEvents>(expectEvents = false)
@ -208,6 +247,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomL
state: RoomListState, state: RoomListState,
onRoomClick: (RoomId) -> Unit = EnsureNeverCalledWithParam(), onRoomClick: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
onSettingsClick: () -> Unit = EnsureNeverCalled(), onSettingsClick: () -> Unit = EnsureNeverCalled(),
onSetUpRecoveryClick: () -> Unit = EnsureNeverCalled(),
onConfirmRecoveryKeyClick: () -> Unit = EnsureNeverCalled(), onConfirmRecoveryKeyClick: () -> Unit = EnsureNeverCalled(),
onCreateRoomClick: () -> Unit = EnsureNeverCalled(), onCreateRoomClick: () -> Unit = EnsureNeverCalled(),
onRoomSettingsClick: (RoomId) -> Unit = EnsureNeverCalledWithParam(), onRoomSettingsClick: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
@ -219,6 +259,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomL
state = state, state = state,
onRoomClick = onRoomClick, onRoomClick = onRoomClick,
onSettingsClick = onSettingsClick, onSettingsClick = onSettingsClick,
onSetUpRecoveryClick = onSetUpRecoveryClick,
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
onCreateRoomClick = onCreateRoomClick, onCreateRoomClick = onCreateRoomClick,
onRoomSettingsClick = onRoomSettingsClick, onRoomSettingsClick = onRoomSettingsClick,

3
features/securebackup/api/src/main/kotlin/io/element/android/features/securebackup/api/SecureBackupEntryPoint.kt

@ -29,6 +29,9 @@ interface SecureBackupEntryPoint : FeatureEntryPoint {
@Parcelize @Parcelize
data object Root : InitialTarget data object Root : InitialTarget
@Parcelize
data object SetUpRecovery : InitialTarget
@Parcelize @Parcelize
data object EnterRecoveryKey : InitialTarget data object EnterRecoveryKey : InitialTarget

1
features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt

@ -50,6 +50,7 @@ class SecureBackupFlowNode @AssistedInject constructor(
backstack = BackStack( backstack = BackStack(
initialElement = when (plugins.filterIsInstance<SecureBackupEntryPoint.Params>().first().initialElement) { initialElement = when (plugins.filterIsInstance<SecureBackupEntryPoint.Params>().first().initialElement) {
SecureBackupEntryPoint.InitialTarget.Root -> NavTarget.Root SecureBackupEntryPoint.InitialTarget.Root -> NavTarget.Root
SecureBackupEntryPoint.InitialTarget.SetUpRecovery -> NavTarget.Setup
SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey -> NavTarget.EnterRecoveryKey SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey -> NavTarget.EnterRecoveryKey
is SecureBackupEntryPoint.InitialTarget.ResetIdentity -> NavTarget.ResetIdentity is SecureBackupEntryPoint.InitialTarget.ResetIdentity -> NavTarget.ResetIdentity
}, },

1
samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt

@ -178,6 +178,7 @@ class RoomListScreen(
state = state, state = state,
onRoomClick = ::onRoomClick, onRoomClick = ::onRoomClick,
onSettingsClick = {}, onSettingsClick = {},
onSetUpRecoveryClick = {},
onConfirmRecoveryKeyClick = {}, onConfirmRecoveryKeyClick = {},
onCreateRoomClick = {}, onCreateRoomClick = {},
onRoomSettingsClick = {}, onRoomSettingsClick = {},

3
tests/uitests/src/test/snapshots/images/features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_en.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:eb59f6e1771481bec3e96b89cbc9255685e6ea154412d7bf7e1351130f42173a
size 28896

3
tests/uitests/src/test/snapshots/images/features.roomlist.impl.components_SetUpRecoveryKeyBanner_Night_0_en.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:413e055704ff0c8dc82321b108c1fa90e7d58af1a781244fbde3daf45d638331
size 27829

3
tests/uitests/src/test/snapshots/images/features.roomlist.impl_RoomListView_Day_11_en.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5870fc3df4bb7330972727601016189e75c358f535f31fe6704837eb866866df
size 100363

3
tests/uitests/src/test/snapshots/images/features.roomlist.impl_RoomListView_Night_11_en.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d236927f6c4cc81f1e9c9b6d405e27e8e96ceb89f9047493b9ab590165d484b2
size 104246

1
tools/localazy/config.json

@ -138,6 +138,7 @@
"screen_roomlist_.*", "screen_roomlist_.*",
"session_verification_banner_.*", "session_verification_banner_.*",
"confirm_recovery_key_banner_.*", "confirm_recovery_key_banner_.*",
"banner\\.set_up_recovery\\..*",
"full_screen_intent_banner_.*", "full_screen_intent_banner_.*",
"screen_migration_.*", "screen_migration_.*",
"screen_invites_.*" "screen_invites_.*"

Loading…
Cancel
Save