Introduce SecurityBannerState to replace Boolean set.

Also get the sessionVerificationService from the matrixClient, instead of injecting it separately.
This commit is contained in:
Benoit Marty 2024-02-20 10:23:48 +01:00 committed by Benoit Marty
parent 7ec876bc8a
commit 4bc977d8dc
6 changed files with 55 additions and 59 deletions

View file

@ -73,7 +73,6 @@ private const val EXTENDED_RANGE_SIZE = 40
class RoomListPresenter @Inject constructor(
private val client: MatrixClient,
private val sessionVerificationService: SessionVerificationService,
private val networkMonitor: NetworkMonitor,
private val snackbarDispatcher: SnackbarDispatcher,
private val inviteStateDataSource: InviteStateDataSource,
@ -87,6 +86,7 @@ class RoomListPresenter @Inject constructor(
private val analyticsService: AnalyticsService,
) : Presenter<RoomListState> {
private val encryptionService: EncryptionService = client.encryptionService()
private val sessionVerificationService: SessionVerificationService = client.sessionVerificationService()
@Composable
override fun present(): RoomListState {
@ -108,22 +108,25 @@ class RoomListPresenter @Inject constructor(
val isMigrating = migrationScreenPresenter.present().isMigrating
// Session verification status (unknown, not verified, verified)
val canVerifySession by sessionVerificationService.canVerifySessionFlow.collectAsState(initial = false)
var verificationPromptDismissed by rememberSaveable { mutableStateOf(false) }
// We combine both values to only display the prompt if the session is not verified and it wasn't dismissed
val displayVerificationPrompt by remember {
derivedStateOf { canVerifySession && !verificationPromptDismissed }
}
var securityBannerDismissed by rememberSaveable { mutableStateOf(false) }
val displayVerificationPrompt by sessionVerificationService.canVerifySessionFlow.collectAsState(initial = false)
val recoveryState by encryptionService.recoveryStateStateFlow.collectAsState()
val secureStorageFlag by featureFlagService.isFeatureEnabledFlow(FeatureFlags.SecureStorage)
.collectAsState(initial = null)
var recoveryKeyPromptDismissed by rememberSaveable { mutableStateOf(false) }
val displayRecoveryKeyPrompt by remember {
derivedStateOf {
secureStorageFlag == true &&
recoveryState == RecoveryState.INCOMPLETE &&
!recoveryKeyPromptDismissed
recoveryState == RecoveryState.INCOMPLETE
}
}
val securityBannerState by remember {
derivedStateOf {
when {
securityBannerDismissed -> SecurityBannerState.None
displayVerificationPrompt -> SecurityBannerState.SessionVerification
displayRecoveryKeyPrompt -> SecurityBannerState.RecoveryKeyConfirmation
else -> SecurityBannerState.None
}
}
}
@ -135,8 +138,8 @@ class RoomListPresenter @Inject constructor(
fun handleEvents(event: RoomListEvents) {
when (event) {
is RoomListEvents.UpdateVisibleRange -> updateVisibleRange(event.range)
RoomListEvents.DismissRequestVerificationPrompt -> verificationPromptDismissed = true
RoomListEvents.DismissRecoveryKeyPrompt -> recoveryKeyPromptDismissed = true
RoomListEvents.DismissRequestVerificationPrompt -> securityBannerDismissed = true
RoomListEvents.DismissRecoveryKeyPrompt -> securityBannerDismissed = true
RoomListEvents.ToggleSearchResults -> searchState.eventSink(RoomListSearchEvents.ToggleSearchVisibility)
is RoomListEvents.ShowContextMenu -> {
coroutineScope.showContextMenu(event, contextMenu)
@ -157,8 +160,7 @@ class RoomListPresenter @Inject constructor(
matrixUser = matrixUser.value,
showAvatarIndicator = showAvatarIndicator,
roomList = roomList,
displayVerificationPrompt = displayVerificationPrompt,
displayRecoveryKeyPrompt = displayRecoveryKeyPrompt,
securityBannerState = securityBannerState,
snackbarMessage = snackbarMessage,
hasNetworkConnection = networkConnectionStatus == NetworkStatus.Online,
invitesState = inviteStateDataSource.inviteState(),

View file

@ -31,8 +31,7 @@ data class RoomListState(
val matrixUser: MatrixUser?,
val showAvatarIndicator: Boolean,
val roomList: AsyncData<ImmutableList<RoomListRoomSummary>>,
val displayVerificationPrompt: Boolean,
val displayRecoveryKeyPrompt: Boolean,
val securityBannerState: SecurityBannerState,
val hasNetworkConnection: Boolean,
val snackbarMessage: SnackbarMessage?,
val invitesState: InvitesState,
@ -62,3 +61,9 @@ enum class InvitesState {
SeenInvites,
NewInvites,
}
enum class SecurityBannerState {
None,
SessionVerification,
RecoveryKeyConfirmation,
}

View file

@ -37,14 +37,14 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
override val values: Sequence<RoomListState>
get() = sequenceOf(
aRoomListState(),
aRoomListState().copy(displayVerificationPrompt = true),
aRoomListState().copy(securityBannerState = SecurityBannerState.SessionVerification),
aRoomListState().copy(snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete)),
aRoomListState().copy(hasNetworkConnection = false),
aRoomListState().copy(invitesState = InvitesState.SeenInvites),
aRoomListState().copy(invitesState = InvitesState.NewInvites),
aRoomListState().copy(contextMenu = aContextMenuShown(roomName = "A nice room name")),
aRoomListState().copy(contextMenu = aContextMenuShown(isFavorite = true)),
aRoomListState().copy(displayRecoveryKeyPrompt = true),
aRoomListState().copy(securityBannerState = SecurityBannerState.RecoveryKeyConfirmation),
aRoomListState().copy(roomList = AsyncData.Success(persistentListOf())),
aRoomListState().copy(roomList = AsyncData.Loading(prevData = RoomListRoomSummaryFactory.createFakeList())),
aRoomListState().copy(matrixUser = null, displayMigrationStatus = true),
@ -58,8 +58,7 @@ internal fun aRoomListState() = RoomListState(
roomList = AsyncData.Success(aRoomListRoomSummaryList()),
hasNetworkConnection = true,
snackbarMessage = null,
displayVerificationPrompt = false,
displayRecoveryKeyPrompt = false,
securityBannerState = SecurityBannerState.None,
invitesState = InvitesState.NoInvites,
contextMenu = RoomListState.ContextMenu.Hidden,
leaveRoomState = aLeaveRoomState(),

View file

@ -225,23 +225,25 @@ private fun RoomListContent(
// FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80
contentPadding = PaddingValues(bottom = 80.dp)
) {
when {
state.displayEmptyState -> Unit
state.displayVerificationPrompt -> {
item {
RequestVerificationHeader(
onVerifyClicked = onVerifyClicked,
onDismissClicked = { state.eventSink(RoomListEvents.DismissRequestVerificationPrompt) }
)
if (state.displayEmptyState.not()) {
when (state.securityBannerState) {
SecurityBannerState.SessionVerification -> {
item {
RequestVerificationHeader(
onVerifyClicked = onVerifyClicked,
onDismissClicked = { state.eventSink(RoomListEvents.DismissRequestVerificationPrompt) }
)
}
}
}
state.displayRecoveryKeyPrompt -> {
item {
ConfirmRecoveryKeyBanner(
onContinueClicked = onOpenSettings,
onDismissClicked = { state.eventSink(RoomListEvents.DismissRecoveryKeyPrompt) }
)
SecurityBannerState.RecoveryKeyConfirmation -> {
item {
ConfirmRecoveryKeyBanner(
onContinueClicked = onOpenSettings,
onDismissClicked = { state.eventSink(RoomListEvents.DismissRecoveryKeyPrompt) }
)
}
}
SecurityBannerState.None -> Unit
}
}