Skip to content

Commit 31d0621

Browse files
authored
Merge pull request #3360 from element-hq/feature/bma/sessionVerificationBannerIsBack
Add banner entry point to set up recovery
2 parents 26b2f5d + d93762b commit 31d0621

File tree

20 files changed

+173
-16
lines changed

20 files changed

+173
-16
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ class LoggedInFlowNode @AssistedInject constructor(
259259
backstack.push(NavTarget.CreateRoom)
260260
}
261261

262+
override fun onSetUpRecoveryClick() {
263+
backstack.push(NavTarget.SecureBackup(initialElement = SecureBackupEntryPoint.InitialTarget.SetUpRecovery))
264+
}
265+
262266
override fun onSessionConfirmRecoveryKeyClick() {
263267
backstack.push(NavTarget.SecureBackup(initialElement = SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey))
264268
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ interface RoomListEntryPoint : FeatureEntryPoint {
3333
fun onRoomClick(roomId: RoomId)
3434
fun onCreateRoomClick()
3535
fun onSettingsClick()
36+
fun onSetUpRecoveryClick()
3637
fun onSessionConfirmRecoveryKeyClick()
3738
fun onRoomSettingsClick(roomId: RoomId)
3839
fun onReportBugClick()

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ class RoomListNode @AssistedInject constructor(
6666
plugins<RoomListEntryPoint.Callback>().forEach { it.onCreateRoomClick() }
6767
}
6868

69+
private fun onSetUpRecoveryClick() {
70+
plugins<RoomListEntryPoint.Callback>().forEach { it.onSetUpRecoveryClick() }
71+
}
72+
6973
private fun onSessionConfirmRecoveryKeyClick() {
7074
plugins<RoomListEntryPoint.Callback>().forEach { it.onSessionConfirmRecoveryKeyClick() }
7175
}
@@ -98,6 +102,7 @@ class RoomListNode @AssistedInject constructor(
98102
onRoomClick = this::onRoomClick,
99103
onSettingsClick = this::onOpenSettings,
100104
onCreateRoomClick = this::onCreateRoomClick,
105+
onSetUpRecoveryClick = this::onSetUpRecoveryClick,
101106
onConfirmRecoveryKeyClick = this::onSessionConfirmRecoveryKeyClick,
102107
onRoomSettingsClick = this::onRoomSettingsClick,
103108
onMenuActionClick = { onMenuActionClick(activity, it) },

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,15 @@ class RoomListPresenter @Inject constructor(
187187
derivedStateOf {
188188
when {
189189
currentSecurityBannerDismissed -> SecurityBannerState.None
190-
recoveryState == RecoveryState.INCOMPLETE &&
191-
syncState == SyncState.Running -> SecurityBannerState.RecoveryKeyConfirmation
190+
syncState == SyncState.Running -> {
191+
when (recoveryState) {
192+
RecoveryState.UNKNOWN,
193+
RecoveryState.DISABLED -> SecurityBannerState.SetUpRecovery
194+
RecoveryState.INCOMPLETE -> SecurityBannerState.RecoveryKeyConfirmation
195+
RecoveryState.WAITING_FOR_SYNC,
196+
RecoveryState.ENABLED -> SecurityBannerState.None
197+
}
198+
}
192199
else -> SecurityBannerState.None
193200
}
194201
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ enum class InvitesState {
6666

6767
enum class SecurityBannerState {
6868
None,
69+
SetUpRecovery,
6970
RecoveryKeyConfirmation,
7071
}
7172

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
5252
aRoomListState(contentState = aSkeletonContentState()),
5353
aRoomListState(matrixUser = MatrixUser(userId = UserId("@id:domain")), contentState = aMigrationContentState()),
5454
aRoomListState(searchState = aRoomListSearchState(isSearchActive = true, query = "Test")),
55+
aRoomListState(contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SetUpRecovery)),
5556
)
5657
}
5758

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ fun RoomListView(
5353
state: RoomListState,
5454
onRoomClick: (RoomId) -> Unit,
5555
onSettingsClick: () -> Unit,
56+
onSetUpRecoveryClick: () -> Unit,
5657
onConfirmRecoveryKeyClick: () -> Unit,
5758
onCreateRoomClick: () -> Unit,
5859
onRoomSettingsClick: (roomId: RoomId) -> Unit,
@@ -78,6 +79,7 @@ fun RoomListView(
7879

7980
RoomListScaffold(
8081
state = state,
82+
onSetUpRecoveryClick = onSetUpRecoveryClick,
8183
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
8284
onRoomClick = onRoomClick,
8385
onOpenSettings = onSettingsClick,
@@ -106,6 +108,7 @@ fun RoomListView(
106108
@Composable
107109
private fun RoomListScaffold(
108110
state: RoomListState,
111+
onSetUpRecoveryClick: () -> Unit,
109112
onConfirmRecoveryKeyClick: () -> Unit,
110113
onRoomClick: (RoomId) -> Unit,
111114
onOpenSettings: () -> Unit,
@@ -142,6 +145,7 @@ private fun RoomListScaffold(
142145
contentState = state.contentState,
143146
filtersState = state.filtersState,
144147
eventSink = state.eventSink,
148+
onSetUpRecoveryClick = onSetUpRecoveryClick,
145149
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
146150
onRoomClick = ::onRoomClick,
147151
onCreateRoomClick = onCreateRoomClick,
@@ -178,6 +182,7 @@ internal fun RoomListViewPreview(@PreviewParameter(RoomListStateProvider::class)
178182
state = state,
179183
onRoomClick = {},
180184
onSettingsClick = {},
185+
onSetUpRecoveryClick = {},
181186
onConfirmRecoveryKeyClick = {},
182187
onCreateRoomClick = {},
183188
onRoomSettingsClick = {},

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

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ fun RoomListContentView(
7070
contentState: RoomListContentState,
7171
filtersState: RoomListFiltersState,
7272
eventSink: (RoomListEvents) -> Unit,
73+
onSetUpRecoveryClick: () -> Unit,
7374
onConfirmRecoveryKeyClick: () -> Unit,
7475
onRoomClick: (RoomListRoomSummary) -> Unit,
7576
onCreateRoomClick: () -> Unit,
@@ -95,6 +96,7 @@ fun RoomListContentView(
9596
state = contentState,
9697
filtersState = filtersState,
9798
eventSink = eventSink,
99+
onSetUpRecoveryClick = onSetUpRecoveryClick,
98100
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
99101
onRoomClick = onRoomClick,
100102
)
@@ -141,6 +143,7 @@ private fun RoomsView(
141143
state: RoomListContentState.Rooms,
142144
filtersState: RoomListFiltersState,
143145
eventSink: (RoomListEvents) -> Unit,
146+
onSetUpRecoveryClick: () -> Unit,
144147
onConfirmRecoveryKeyClick: () -> Unit,
145148
onRoomClick: (RoomListRoomSummary) -> Unit,
146149
modifier: Modifier = Modifier,
@@ -154,6 +157,7 @@ private fun RoomsView(
154157
RoomsViewList(
155158
state = state,
156159
eventSink = eventSink,
160+
onSetUpRecoveryClick = onSetUpRecoveryClick,
157161
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
158162
onRoomClick = onRoomClick,
159163
modifier = modifier.fillMaxSize(),
@@ -165,6 +169,7 @@ private fun RoomsView(
165169
private fun RoomsViewList(
166170
state: RoomListContentState.Rooms,
167171
eventSink: (RoomListEvents) -> Unit,
172+
onSetUpRecoveryClick: () -> Unit,
168173
onConfirmRecoveryKeyClick: () -> Unit,
169174
onRoomClick: (RoomListRoomSummary) -> Unit,
170175
modifier: Modifier = Modifier,
@@ -188,21 +193,27 @@ private fun RoomsViewList(
188193
// FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80
189194
contentPadding = PaddingValues(bottom = 80.dp)
190195
) {
191-
if (state.securityBannerState != SecurityBannerState.None) {
192-
when (state.securityBannerState) {
193-
SecurityBannerState.RecoveryKeyConfirmation -> {
194-
item {
195-
ConfirmRecoveryKeyBanner(
196-
onContinueClick = onConfirmRecoveryKeyClick,
197-
onDismissClick = { updatedEventSink(RoomListEvents.DismissRecoveryKeyPrompt) }
198-
)
199-
}
196+
when (state.securityBannerState) {
197+
SecurityBannerState.SetUpRecovery -> {
198+
item {
199+
SetUpRecoveryKeyBanner(
200+
onContinueClick = onSetUpRecoveryClick,
201+
onDismissClick = { updatedEventSink(RoomListEvents.DismissRecoveryKeyPrompt) }
202+
)
200203
}
201-
else -> Unit
202204
}
203-
} else if (state.fullScreenIntentPermissionsState.shouldDisplayBanner) {
204-
item {
205-
FullScreenIntentPermissionBanner(state = state.fullScreenIntentPermissionsState)
205+
SecurityBannerState.RecoveryKeyConfirmation -> {
206+
item {
207+
ConfirmRecoveryKeyBanner(
208+
onContinueClick = onConfirmRecoveryKeyClick,
209+
onDismissClick = { updatedEventSink(RoomListEvents.DismissRecoveryKeyPrompt) }
210+
)
211+
}
212+
}
213+
SecurityBannerState.None -> if (state.fullScreenIntentPermissionsState.shouldDisplayBanner) {
214+
item {
215+
FullScreenIntentPermissionBanner(state = state.fullScreenIntentPermissionsState)
216+
}
206217
}
207218
}
208219

@@ -276,6 +287,7 @@ internal fun RoomListContentViewPreview(@PreviewParameter(RoomListContentStatePr
276287
filterSelectionStates = RoomListFilter.entries.map { FilterSelectionState(it, isSelected = true) }
277288
),
278289
eventSink = {},
290+
onSetUpRecoveryClick = {},
279291
onConfirmRecoveryKeyClick = {},
280292
onRoomClick = {},
281293
onCreateRoomClick = {},
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2024 New Vector Ltd
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.element.android.features.roomlist.impl.components
18+
19+
import androidx.compose.runtime.Composable
20+
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.res.stringResource
22+
import io.element.android.features.roomlist.impl.R
23+
import io.element.android.libraries.designsystem.atomic.molecules.DialogLikeBannerMolecule
24+
import io.element.android.libraries.designsystem.preview.ElementPreview
25+
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
26+
27+
@Composable
28+
internal fun SetUpRecoveryKeyBanner(
29+
onContinueClick: () -> Unit,
30+
onDismissClick: () -> Unit,
31+
modifier: Modifier = Modifier,
32+
) {
33+
DialogLikeBannerMolecule(
34+
modifier = modifier,
35+
title = stringResource(R.string.banner_set_up_recovery_title),
36+
content = stringResource(R.string.banner_set_up_recovery_content),
37+
onSubmitClick = onContinueClick,
38+
onDismissClick = onDismissClick,
39+
)
40+
}
41+
42+
@PreviewsDayNight
43+
@Composable
44+
internal fun SetUpRecoveryKeyBannerPreview() = ElementPreview {
45+
SetUpRecoveryKeyBanner(
46+
onContinueClick = {},
47+
onDismissClick = {},
48+
)
49+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
3+
<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>
4+
<string name="banner_set_up_recovery_title">"Set up recovery"</string>
35
<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>
46
<string name="confirm_recovery_key_banner_title">"Enter your recovery key"</string>
57
<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>

0 commit comments

Comments
 (0)