Merge pull request #2013 from element-hq/feature/bma/logoutWording
Fix title of sign out screen regarding the different states
This commit is contained in:
commit
4c987c5b3f
21 changed files with 102 additions and 29 deletions
|
|
@ -28,9 +28,11 @@ import androidx.compose.runtime.setValue
|
|||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.core.bool.orTrue
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupState
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -70,6 +72,19 @@ class LogoutPresenter @Inject constructor(
|
|||
isLastSession = encryptionService.isLastDevice().getOrNull() ?: false
|
||||
}
|
||||
|
||||
val backupState by encryptionService.backupStateStateFlow.collectAsState()
|
||||
val recoveryState by encryptionService.recoveryStateStateFlow.collectAsState()
|
||||
|
||||
val doesBackupExistOnServerAction: MutableState<Async<Boolean>> = remember {
|
||||
mutableStateOf(Async.Uninitialized)
|
||||
}
|
||||
|
||||
LaunchedEffect(backupState) {
|
||||
if (backupState == BackupState.UNKNOWN) {
|
||||
getKeyBackupStatus(doesBackupExistOnServerAction)
|
||||
}
|
||||
}
|
||||
|
||||
fun handleEvents(event: LogoutEvents) {
|
||||
when (event) {
|
||||
is LogoutEvents.Logout -> {
|
||||
|
|
@ -89,6 +104,9 @@ class LogoutPresenter @Inject constructor(
|
|||
|
||||
return LogoutState(
|
||||
isLastSession = isLastSession,
|
||||
backupState = backupState,
|
||||
doesBackupExistOnServer = doesBackupExistOnServerAction.value.dataOrNull().orTrue(),
|
||||
recoveryState = recoveryState,
|
||||
backupUploadState = backupUploadState,
|
||||
showConfirmationDialog = showLogoutDialog,
|
||||
logoutAction = logoutAction.value,
|
||||
|
|
@ -96,6 +114,12 @@ class LogoutPresenter @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.getKeyBackupStatus(action: MutableState<Async<Boolean>>) = launch {
|
||||
suspend {
|
||||
encryptionService.doesBackupExistOnServer().getOrThrow()
|
||||
}.runCatchingUpdatingState(action)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.logout(
|
||||
logoutAction: MutableState<Async<String?>>,
|
||||
ignoreSdkError: Boolean,
|
||||
|
|
|
|||
|
|
@ -17,10 +17,15 @@
|
|||
package io.element.android.features.logout.impl
|
||||
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupState
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
|
||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||
|
||||
data class LogoutState(
|
||||
val isLastSession: Boolean,
|
||||
val backupState: BackupState,
|
||||
val doesBackupExistOnServer: Boolean,
|
||||
val recoveryState: RecoveryState,
|
||||
val backupUploadState: BackupUploadState,
|
||||
val showConfirmationDialog: Boolean,
|
||||
val logoutAction: Async<String?>,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ package io.element.android.features.logout.impl
|
|||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupState
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
|
||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||
import io.element.android.libraries.matrix.api.encryption.SteadyStateException
|
||||
|
||||
open class LogoutStateProvider : PreviewParameterProvider<LogoutState> {
|
||||
|
|
@ -32,16 +34,26 @@ open class LogoutStateProvider : PreviewParameterProvider<LogoutState> {
|
|||
aLogoutState(logoutAction = Async.Loading()),
|
||||
aLogoutState(logoutAction = Async.Failure(Exception("Failed to logout"))),
|
||||
aLogoutState(backupUploadState = BackupUploadState.SteadyException(SteadyStateException.Connection("No network"))),
|
||||
// Last session no recovery
|
||||
aLogoutState(isLastSession = true, recoveryState = RecoveryState.DISABLED),
|
||||
// Last session no backup
|
||||
aLogoutState(isLastSession = true, backupState = BackupState.UNKNOWN, doesBackupExistOnServer = false),
|
||||
)
|
||||
}
|
||||
|
||||
fun aLogoutState(
|
||||
isLastSession: Boolean = false,
|
||||
backupState: BackupState = BackupState.ENABLED,
|
||||
doesBackupExistOnServer: Boolean = true,
|
||||
recoveryState: RecoveryState = RecoveryState.ENABLED,
|
||||
backupUploadState: BackupUploadState = BackupUploadState.Unknown,
|
||||
showConfirmationDialog: Boolean = false,
|
||||
logoutAction: Async<String?> = Async.Uninitialized,
|
||||
) = LogoutState(
|
||||
isLastSession = isLastSession,
|
||||
backupState = backupState,
|
||||
doesBackupExistOnServer = doesBackupExistOnServer,
|
||||
recoveryState = recoveryState,
|
||||
backupUploadState = backupUploadState,
|
||||
showConfirmationDialog = showConfirmationDialog,
|
||||
logoutAction = logoutAction,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@ 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.progressIndicatorTrackColor
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupState
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
|
||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||
import io.element.android.libraries.matrix.api.encryption.SteadyStateException
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
|
|
@ -120,7 +122,15 @@ fun LogoutView(
|
|||
private fun title(state: LogoutState): String {
|
||||
return when {
|
||||
state.backupUploadState.isBackingUp() -> stringResource(id = R.string.screen_signout_key_backup_ongoing_title)
|
||||
state.isLastSession -> stringResource(id = R.string.screen_signout_key_backup_disabled_title)
|
||||
state.isLastSession -> {
|
||||
if (state.recoveryState != RecoveryState.ENABLED) {
|
||||
stringResource(id = R.string.screen_signout_recovery_disabled_title)
|
||||
} else if (state.backupState == BackupState.UNKNOWN && state.doesBackupExistOnServer.not()) {
|
||||
stringResource(id = R.string.screen_signout_key_backup_disabled_title)
|
||||
} else {
|
||||
stringResource(id = R.string.screen_signout_save_recovery_key_title)
|
||||
}
|
||||
}
|
||||
else -> stringResource(CommonStrings.action_signout)
|
||||
}
|
||||
}
|
||||
|
|
@ -138,10 +148,10 @@ private fun subtitle(state: LogoutState): String? {
|
|||
|
||||
private fun BackupUploadState.isBackingUp(): Boolean {
|
||||
return when (this) {
|
||||
BackupUploadState.Unknown,
|
||||
BackupUploadState.Waiting,
|
||||
is BackupUploadState.Uploading -> true
|
||||
is BackupUploadState.SteadyException -> exception is SteadyStateException.Connection
|
||||
BackupUploadState.Unknown,
|
||||
BackupUploadState.Done,
|
||||
BackupUploadState.Error -> false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@ import io.element.android.libraries.architecture.Async
|
|||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupState
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
|
||||
|
|
@ -50,6 +52,9 @@ class LogoutPresenterTest {
|
|||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
assertThat(initialState.isLastSession).isFalse()
|
||||
assertThat(initialState.backupState).isEqualTo(BackupState.UNKNOWN)
|
||||
assertThat(initialState.doesBackupExistOnServer).isTrue()
|
||||
assertThat(initialState.recoveryState).isEqualTo(RecoveryState.UNKNOWN)
|
||||
assertThat(initialState.backupUploadState).isEqualTo(BackupUploadState.Unknown)
|
||||
assertThat(initialState.showConfirmationDialog).isFalse()
|
||||
assertThat(initialState.logoutAction).isEqualTo(Async.Uninitialized)
|
||||
|
|
@ -93,14 +98,15 @@ class LogoutPresenterTest {
|
|||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.isLastSession).isFalse()
|
||||
assertThat(initialState.backupUploadState).isEqualTo(BackupUploadState.Unknown)
|
||||
assertThat(initialState.showConfirmationDialog).isFalse()
|
||||
assertThat(initialState.logoutAction).isEqualTo(Async.Uninitialized)
|
||||
skipItems(1)
|
||||
val waitingState = awaitItem()
|
||||
assertThat(waitingState.backupUploadState).isEqualTo(BackupUploadState.Waiting)
|
||||
skipItems(1)
|
||||
val uploadingState = awaitItem()
|
||||
assertThat(uploadingState.backupUploadState).isEqualTo(BackupUploadState.Uploading(backedUpCount = 1, totalCount = 2))
|
||||
val doneState = awaitItem()
|
||||
|
|
@ -155,7 +161,8 @@ class LogoutPresenterTest {
|
|||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink.invoke(LogoutEvents.Logout(ignoreSdkError = false))
|
||||
val confirmationState = awaitItem()
|
||||
assertThat(confirmationState.showConfirmationDialog).isTrue()
|
||||
|
|
@ -164,6 +171,7 @@ class LogoutPresenterTest {
|
|||
val loadingState = awaitItem()
|
||||
assertThat(loadingState.showConfirmationDialog).isFalse()
|
||||
assertThat(loadingState.logoutAction).isInstanceOf(Async.Loading::class.java)
|
||||
skipItems(1)
|
||||
val errorState = awaitItem()
|
||||
assertThat(errorState.logoutAction).isEqualTo(Async.Failure<LogoutState>(A_THROWABLE))
|
||||
errorState.eventSink.invoke(LogoutEvents.CloseDialogs)
|
||||
|
|
@ -183,7 +191,8 @@ class LogoutPresenterTest {
|
|||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink.invoke(LogoutEvents.Logout(ignoreSdkError = false))
|
||||
val confirmationState = awaitItem()
|
||||
assertThat(confirmationState.showConfirmationDialog).isTrue()
|
||||
|
|
@ -192,6 +201,7 @@ class LogoutPresenterTest {
|
|||
val loadingState = awaitItem()
|
||||
assertThat(loadingState.showConfirmationDialog).isFalse()
|
||||
assertThat(loadingState.logoutAction).isInstanceOf(Async.Loading::class.java)
|
||||
skipItems(1)
|
||||
val errorState = awaitItem()
|
||||
assertThat(errorState.logoutAction).isEqualTo(Async.Failure<LogoutState>(A_THROWABLE))
|
||||
errorState.eventSink.invoke(LogoutEvents.Logout(ignoreSdkError = true))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0566f93f37532625a0c647992f25c2cbae9e944ab51629ad1c02322d28bad72e
|
||||
size 29115
|
||||
oid sha256:78edb2f0cbb3a7c975999aa31f90e5a82e7b73a21f2923e420f364da3c0118fd
|
||||
size 13706
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5845034f94d3e3452bdda9e04d8609385154b3462ac98abb267819a7d55e1672
|
||||
size 33099
|
||||
oid sha256:186d3f45a3e8b294e523ede9787563399d97b26d7181ad687afcd8b48f8be506
|
||||
size 41247
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2c2f057c86716407a4cd3491612f57b9d4b800cf4ef749c2e6dce3e12fbbf632
|
||||
size 37972
|
||||
oid sha256:186d3f45a3e8b294e523ede9787563399d97b26d7181ad687afcd8b48f8be506
|
||||
size 41247
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:475436dfdc616c2c5111e9dfbbf058e57fa12b05c82064e9a778d56cdeb05923
|
||||
size 34939
|
||||
oid sha256:2d8dfacb3767fe7e9de7996cd0fb9bcb7f208e49498bfdc7b599546669b7b396
|
||||
size 27632
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a7001f904e0b190b8846cf0d440a972d1a6097fc168caee135469a2dbb39788c
|
||||
size 31590
|
||||
oid sha256:51528fe646b2ac7f679861af28443b22fe1a710586ac70aa730d98cf7c1e8856
|
||||
size 21842
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:77fe1e9484c72dc9572a810941cc83ecd208aa080d59417e409c69edbea978d5
|
||||
size 33484
|
||||
oid sha256:47f4ac4fb71f8a4adc3890101244c4ee9fbbf87d0da0e0381a85792b79896a5f
|
||||
size 26372
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:87010d4aae66e1030d4b9557e4f065df777324495459c08513040e6793d2d00d
|
||||
size 36675
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2c2f057c86716407a4cd3491612f57b9d4b800cf4ef749c2e6dce3e12fbbf632
|
||||
size 37972
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ccdef8b261183673b56d0405b0a2b233eddc0537af600f9071d1b0b0bb495e3b
|
||||
size 27390
|
||||
oid sha256:dd5acfa31ca9994634286aa59bdb67d86e438165296164db82e152cd56868585
|
||||
size 13044
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dbbd4c82b8f8a1c283074c51968b7e097595721cb25ba2612b9fff5e2c1a5c07
|
||||
size 30999
|
||||
oid sha256:49df4ac1a7ec108308b82d0fdb6f0e0d8ca2063960070fa9865562e59774ec21
|
||||
size 38623
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:52bf6e6334dd36e2e39f6957a60c7d54839caffdf47a32a0bb463124fc2c27d4
|
||||
size 35820
|
||||
oid sha256:49df4ac1a7ec108308b82d0fdb6f0e0d8ca2063960070fa9865562e59774ec21
|
||||
size 38623
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:426c68f5506c8f8a203a3d017130bebd556146b241d044d4ba9160b8029a4fd6
|
||||
size 30490
|
||||
oid sha256:51af5a971e3bb5958646ec1866ba41fd4d46e281713573b005bc71b4762ec7b4
|
||||
size 24085
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:277730c5d3e711f28b8405f90b004268343845a1b528860cfbffcf47c7e39086
|
||||
size 28511
|
||||
oid sha256:6efe41b16360b4cfc891a5ffc99ff147ea5c5324341d5f8b8a2f574d360b5aad
|
||||
size 19117
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f3814c6d92191053e08d6c6b7c4ad7c52cdf868795bd50771d03c08885d2c298
|
||||
size 29271
|
||||
oid sha256:6a2a05a5d4f528302ca1a6f8bd799418f97d511bb808dadbfe806077ab2a9bab
|
||||
size 22756
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3961ac676e29ac3d6f8dede3aed1c0c22d400e6a95ca8c4333691102f1616c42
|
||||
size 34922
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:52bf6e6334dd36e2e39f6957a60c7d54839caffdf47a32a0bb463124fc2c27d4
|
||||
size 35820
|
||||
Loading…
Add table
Add a link
Reference in a new issue