PM-9443: Update empty search state (#3409)

This commit is contained in:
Shannon Draeker 2024-07-08 14:26:34 -06:00 committed by GitHub
parent e9057cb866
commit 99c50a3fc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 78 additions and 3 deletions

View file

@ -30,6 +30,7 @@ fun VaultItemListingEmpty(
VaultNoItems(
policyDisablesSend = policyDisablesSend,
message = state.message(),
buttonText = state.buttonText(),
modifier = modifier,
addItemClickAction = addItemClickAction,
)

View file

@ -1044,6 +1044,7 @@ data class VaultItemListingState(
data class NoItems(
val message: Text,
val shouldShowAddButton: Boolean,
val buttonText: Text,
) : ViewState() {
override val isPullToRefreshEnabled: Boolean get() = true
}

View file

@ -161,6 +161,10 @@ fun VaultData.toViewState(
?.uri
?.toHostOrPathOrNull()
?.let { R.string.no_items_for_uri.asText(it) }
?: fido2CreationData
?.origin
?.toHostOrPathOrNull()
?.let { R.string.no_items_for_uri.asText(it) }
?: run {
when (itemListingType) {
is VaultItemListingState.ItemListingType.Vault.Folder -> {
@ -189,6 +193,11 @@ fun VaultData.toViewState(
VaultItemListingState.ViewState.NoItems(
message = message,
shouldShowAddButton = shouldShowAddButton,
buttonText = if (fido2CreationData != null) {
R.string.save_passkey_as_new_login.asText()
} else {
R.string.add_an_item.asText()
},
)
}
}
@ -213,6 +222,7 @@ fun List<SendView>.toViewState(
VaultItemListingState.ViewState.NoItems(
message = R.string.no_items.asText(),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
)
}

View file

@ -6,10 +6,12 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -20,6 +22,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.components.text.BitwardenPolicyWarningText
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
/**
* No items view for the [VaultScreen].
@ -30,6 +33,7 @@ fun VaultNoItems(
policyDisablesSend: Boolean,
modifier: Modifier = Modifier,
message: String = stringResource(id = R.string.no_items),
buttonText: String = stringResource(id = R.string.add_an_item),
) {
Column(
modifier = modifier.verticalScroll(rememberScrollState()),
@ -46,6 +50,17 @@ fun VaultNoItems(
Spacer(modifier = Modifier.weight(1F))
Icon(
painter = rememberVectorPainter(id = R.drawable.ic_search),
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier
.size(74.dp)
.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.height(24.dp))
Text(
textAlign = TextAlign.Center,
modifier = Modifier
@ -68,7 +83,7 @@ fun VaultNoItems(
),
) {
Text(
text = stringResource(id = R.string.add_an_item),
text = buttonText,
style = MaterialTheme.typography.labelLarge,
)
}

View file

@ -352,6 +352,7 @@ class VaultItemListingScreenTest : BaseComposeTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = "There are no Sends in your account.".asText(),
shouldShowAddButton = true,
buttonText = "Add an Item".asText(),
),
)
}
@ -381,12 +382,13 @@ class VaultItemListingScreenTest : BaseComposeTest() {
}
@Test
fun `add an item button click should send AddItemClick action`() {
fun `Add an Item button click should send AddItemClick action`() {
mutableStateFlow.update {
it.copy(
viewState = VaultItemListingState.ViewState.NoItems(
message = "There are no items in your vault.".asText(),
shouldShowAddButton = true,
buttonText = "Add an Item".asText(),
),
)
}
@ -487,6 +489,7 @@ class VaultItemListingScreenTest : BaseComposeTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = "There are no items in your vault.".asText(),
shouldShowAddButton = true,
buttonText = "Add an Item".asText(),
),
)
}
@ -509,6 +512,7 @@ class VaultItemListingScreenTest : BaseComposeTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = "There are no items in your vault.".asText(),
shouldShowAddButton = true,
buttonText = "Add an Item".asText(),
),
)
}
@ -525,7 +529,7 @@ class VaultItemListingScreenTest : BaseComposeTest() {
}
@Test
fun `Add an item button should be displayed according to state`() {
fun `Add an Item button should be displayed according to state`() {
mutableStateFlow.update { DEFAULT_STATE }
composeTestRule
.onNodeWithText(text = "Add an Item")
@ -536,6 +540,7 @@ class VaultItemListingScreenTest : BaseComposeTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = "There are no items in your vault.".asText(),
shouldShowAddButton = true,
buttonText = "Add an Item".asText(),
),
)
}
@ -549,6 +554,7 @@ class VaultItemListingScreenTest : BaseComposeTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = "There are no items in your vault.".asText(),
shouldShowAddButton = false,
buttonText = "Add an Item".asText(),
),
)
}
@ -564,12 +570,16 @@ class VaultItemListingScreenTest : BaseComposeTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = "There are no items in your vault.".asText(),
shouldShowAddButton = true,
buttonText = "Save passkey as new login".asText(),
),
)
}
composeTestRule
.onNodeWithText(text = "There are no items in your vault.")
.assertIsDisplayed()
composeTestRule
.onNodeWithText(text = "Save passkey as new login")
.assertIsDisplayed()
}
@Test

View file

@ -1067,6 +1067,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = R.string.no_items.asText(),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
),
),
viewModel.stateFlow.value,
@ -1095,6 +1096,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = R.string.no_items.asText(),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
),
),
viewModel.stateFlow.value,
@ -1164,6 +1166,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = R.string.no_items.asText(),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
),
),
viewModel.stateFlow.value,
@ -1190,6 +1193,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = R.string.no_items.asText(),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
),
),
viewModel.stateFlow.value,
@ -1277,6 +1281,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = R.string.no_items.asText(),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
),
),
viewModel.stateFlow.value,
@ -1306,6 +1311,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = R.string.no_items.asText(),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
),
),
viewModel.stateFlow.value,
@ -1391,6 +1397,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = R.string.no_items.asText(),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
),
),
viewModel.stateFlow.value,
@ -1419,6 +1426,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewState = VaultItemListingState.ViewState.NoItems(
message = R.string.no_items.asText(),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
),
),
viewModel.stateFlow.value,

View file

@ -1,5 +1,6 @@
package com.x8bit.bitwarden.ui.vault.feature.itemlisting.util
import android.content.pm.SigningInfo
import android.net.Uri
import com.bitwarden.send.SendType
import com.bitwarden.vault.CipherRepromptType
@ -7,6 +8,7 @@ import com.bitwarden.vault.CipherType
import com.bitwarden.vault.CipherView
import com.bitwarden.vault.FolderView
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2CredentialRequest
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
import com.x8bit.bitwarden.data.platform.repository.model.Environment
import com.x8bit.bitwarden.data.platform.repository.util.baseIconUrl
@ -513,6 +515,7 @@ class VaultItemListingDataExtensionsTest {
VaultItemListingState.ViewState.NoItems(
message = R.string.no_items_trash.asText(),
shouldShowAddButton = false,
buttonText = R.string.add_an_item.asText(),
),
vaultData.toViewState(
vaultFilterType = VaultFilterType.AllVaults,
@ -530,6 +533,7 @@ class VaultItemListingDataExtensionsTest {
VaultItemListingState.ViewState.NoItems(
message = R.string.no_items_folder.asText(),
shouldShowAddButton = false,
buttonText = R.string.add_an_item.asText(),
),
vaultData.toViewState(
vaultFilterType = VaultFilterType.AllVaults,
@ -549,6 +553,7 @@ class VaultItemListingDataExtensionsTest {
VaultItemListingState.ViewState.NoItems(
message = R.string.no_items.asText(),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
),
vaultData.toViewState(
vaultFilterType = VaultFilterType.AllVaults,
@ -566,6 +571,7 @@ class VaultItemListingDataExtensionsTest {
VaultItemListingState.ViewState.NoItems(
message = R.string.no_items_for_uri.asText("www.test.com"),
shouldShowAddButton = true,
buttonText = R.string.add_an_item.asText(),
),
vaultData.toViewState(
vaultFilterType = VaultFilterType.AllVaults,
@ -580,6 +586,30 @@ class VaultItemListingDataExtensionsTest {
hasMasterPassword = true,
),
)
// Autofill passkey
assertEquals(
VaultItemListingState.ViewState.NoItems(
message = R.string.no_items_for_uri.asText("www.test.com"),
shouldShowAddButton = true,
buttonText = R.string.save_passkey_as_new_login.asText(),
),
vaultData.toViewState(
vaultFilterType = VaultFilterType.AllVaults,
itemListingType = VaultItemListingState.ItemListingType.Vault.Login,
isIconLoadingDisabled = false,
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
autofillSelectionData = null,
fido2CreationData = Fido2CredentialRequest(
userId = "",
requestJson = "",
packageName = "",
signingInfo = SigningInfo(),
origin = "https://www.test.com",
),
hasMasterPassword = true,
),
)
}
@Test