From 92368b25356d793ce4886732aa2dd30a68835cd2 Mon Sep 17 00:00:00 2001 From: Brian Yencho Date: Fri, 15 Dec 2023 12:14:01 -0600 Subject: [PATCH] Ensure FAB is hidden for some Vault Screen states (#401) --- .../ui/vault/feature/vault/VaultScreen.kt | 2 +- .../ui/vault/feature/vault/VaultViewModel.kt | 22 +++++++++++++++---- .../ui/vault/feature/vault/VaultScreenTest.kt | 19 ++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt index d3300f6032..ad07a71fd8 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt @@ -265,7 +265,7 @@ private fun VaultScreenScaffold( }, floatingActionButton = { AnimatedVisibility( - visible = !accountMenuVisible, + visible = state.viewState.hasFab && !accountMenuVisible, enter = scaleIn(), exit = scaleOut(), ) { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt index 8464f5c04b..86d280625b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt @@ -304,17 +304,27 @@ data class VaultState( @Parcelize sealed class ViewState : Parcelable { + /** + * Determines whether or not the Floating Action Button (FAB) should be shown for the + * given state. + */ + abstract val hasFab: Boolean + /** * Loading state for the [VaultScreen], signifying that the content is being processed. */ @Parcelize - data object Loading : ViewState() + data object Loading : ViewState() { + override val hasFab: Boolean get() = false + } /** * Represents a state where the [VaultScreen] has no items to display. */ @Parcelize - data object NoItems : ViewState() + data object NoItems : ViewState() { + override val hasFab: Boolean get() = true + } /** * Represents a state where the [VaultScreen] is unable to display data due to an error @@ -323,7 +333,9 @@ data class VaultState( @Parcelize data class Error( val message: Text, - ) : ViewState() + ) : ViewState() { + override val hasFab: Boolean get() = false + } /** * Content state for the [VaultScreen] showing the actual content or items. @@ -349,7 +361,9 @@ data class VaultState( val noFolderItems: List, val collectionItems: List, val trashItemsCount: Int, - ) : ViewState() + ) : ViewState() { + override val hasFab: Boolean get() = true + } /** * Represents a folder item with a name and item count. diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt index ff25bf0911..9e7dace9aa 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt @@ -283,6 +283,25 @@ class VaultScreenTest : BaseComposeTest() { verify { viewModel.trySendAction(VaultAction.ExitConfirmationClick) } } + @Test + fun `floating action button should be shown or hidden according to the state`() { + val fabDescription = "Add item" + + mutableStateFlow.update { it.copy(viewState = VaultState.ViewState.Loading) } + composeTestRule.onNodeWithContentDescription(fabDescription).assertDoesNotExist() + + mutableStateFlow.update { + it.copy(viewState = VaultState.ViewState.Error("Error".asText())) + } + composeTestRule.onNodeWithContentDescription(fabDescription).assertDoesNotExist() + + mutableStateFlow.update { it.copy(viewState = VaultState.ViewState.NoItems) } + composeTestRule.onNodeWithContentDescription(fabDescription).assertIsDisplayed() + + mutableStateFlow.update { it.copy(viewState = DEFAULT_CONTENT_VIEW_STATE) } + composeTestRule.onNodeWithContentDescription(fabDescription).assertIsDisplayed() + } + @Test fun `error dialog should be shown or hidden according to the state`() { val errorTitle = "Error title"