From 5279e6d18cdfa58c97dcb380f70c401d8d9b75f8 Mon Sep 17 00:00:00 2001 From: David Perez Date: Thu, 27 Mar 2025 13:52:38 -0500 Subject: [PATCH] PM-19547: Delay the delete account success dialog to avoid flicker (#4927) --- .../deleteaccount/DeleteAccountViewModel.kt | 15 +++++++++- .../DeleteAccountViewModelTest.kt | 29 +++++++++++-------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountViewModel.kt index b7537c88f8..2becd3165c 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountViewModel.kt @@ -11,6 +11,7 @@ import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.util.Text import com.x8bit.bitwarden.ui.platform.base.util.asText import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update @@ -20,6 +21,8 @@ import javax.inject.Inject private const val KEY_STATE = "state" +private const val SUCCESS_DIALOG_DELAY = 550L + /** * View model for the [DeleteAccountScreen]. */ @@ -115,7 +118,17 @@ class DeleteAccountViewModel @Inject constructor( ) { when (val result = action.result) { DeleteAccountResult.Success -> { - updateDialogState(DeleteAccountState.DeleteAccountDialog.DeleteSuccess) + viewModelScope.launch { + // When deleting an account, the current activity is recreated and therefore + // the composition takes place twice. Adding this delay prevents the dialog + // from flashing when it is re-created. + delay(timeMillis = SUCCESS_DIALOG_DELAY) + sendAction( + action = DeleteAccountAction.Internal.UpdateDialogState( + dialog = DeleteAccountState.DeleteAccountDialog.DeleteSuccess, + ), + ) + } } is DeleteAccountResult.Error -> { diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountViewModelTest.kt index 9fb084d7ac..d65cae6abc 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountViewModelTest.kt @@ -87,18 +87,23 @@ class DeleteAccountViewModelTest : BaseViewModelTest() { authRepo.deleteAccountWithMasterPassword(masterPassword) } returns DeleteAccountResult.Success - viewModel.trySendAction( - DeleteAccountAction.DeleteAccountConfirmDialogClick( - masterPassword, - ), - ) - - assertEquals( - DEFAULT_STATE.copy(dialog = DeleteAccountState.DeleteAccountDialog.DeleteSuccess), - viewModel.stateFlow.value, - ) - - coVerify { + viewModel.stateFlow.test { + assertEquals(DEFAULT_STATE, awaitItem()) + viewModel.trySendAction( + action = DeleteAccountAction.DeleteAccountConfirmDialogClick(masterPassword), + ) + assertEquals( + DEFAULT_STATE.copy(dialog = DeleteAccountState.DeleteAccountDialog.Loading), + awaitItem(), + ) + assertEquals( + DEFAULT_STATE.copy( + dialog = DeleteAccountState.DeleteAccountDialog.DeleteSuccess, + ), + awaitItem(), + ) + } + coVerify(exactly = 1) { authRepo.deleteAccountWithMasterPassword(masterPassword) } }