BIT-2128: Item creation screen cipher type error (#1169)

This commit is contained in:
Ramsey Smith
2024-03-26 11:32:03 -06:00
committed by Álison Fernandes
parent 25ceaf8c0b
commit 992bafc16c
21 changed files with 279 additions and 77 deletions

View File

@@ -40,6 +40,7 @@ import com.x8bit.bitwarden.ui.tools.feature.send.addsend.navigateToAddSend
import com.x8bit.bitwarden.ui.vault.feature.addedit.navigateToVaultAddEdit
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.navigateToVaultItemListingAsRoot
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import java.util.concurrent.atomic.AtomicReference
@@ -147,7 +148,9 @@ fun RootNavScreen(
is RootNavState.VaultUnlockedForAutofillSave -> {
navController.navigateToVaultUnlockedGraph(rootNavOptions)
navController.navigateToVaultAddEdit(
vaultAddEditType = VaultAddEditType.AddItem,
vaultAddEditType = VaultAddEditType.AddItem(
vaultItemCipherType = VaultItemCipherType.LOGIN,
),
navOptions = rootNavOptions,
)
}

View File

@@ -68,7 +68,7 @@ fun NavGraphBuilder.vaultUnlockedGraph(
onNavigateBack = { navController.popBackStack() },
onNavigateToVaultItemScreen = { navController.navigateToVaultItem(vaultItemId = it) },
onNavigateToVaultAddItemScreen = {
navController.navigateToVaultAddEdit(VaultAddEditType.AddItem)
navController.navigateToVaultAddEdit(VaultAddEditType.AddItem(it))
},
onNavigateToSearchVault = { navController.navigateToSearch(searchType = it) },
onNavigateToVaultEditItemScreen = {
@@ -79,7 +79,7 @@ fun NavGraphBuilder.vaultUnlockedGraph(
onNavigateToExportVault = { navController.navigateToExportVault() },
onNavigateToFolders = { navController.navigateToFolders() },
onNavigateToVaultAddItem = {
navController.navigateToVaultAddEdit(VaultAddEditType.AddItem)
navController.navigateToVaultAddEdit(VaultAddEditType.AddItem(it))
},
onNavigateToVaultItem = { navController.navigateToVaultItem(it) },
onNavigateToVaultEditItem = {

View File

@@ -5,6 +5,7 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import com.x8bit.bitwarden.ui.platform.base.util.composableWithStayTransitions
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
/**
* The functions below pertain to entry into the [VaultUnlockedNavBarScreen].
@@ -23,7 +24,7 @@ fun NavController.navigateToVaultUnlockedNavBar(navOptions: NavOptions? = null)
*/
@Suppress("LongParameterList")
fun NavGraphBuilder.vaultUnlockedNavBarDestination(
onNavigateToVaultAddItem: () -> Unit,
onNavigateToVaultAddItem: (VaultItemCipherType) -> Unit,
onNavigateToVaultItem: (vaultItemId: String) -> Unit,
onNavigateToVaultEditItem: (vaultItemId: String) -> Unit,
onNavigateToSearchSend: (searchType: SearchType.Sends) -> Unit,

View File

@@ -63,6 +63,7 @@ import com.x8bit.bitwarden.ui.tools.feature.send.sendGraph
import com.x8bit.bitwarden.ui.vault.feature.vault.VAULT_GRAPH_ROUTE
import com.x8bit.bitwarden.ui.vault.feature.vault.navigateToVaultGraph
import com.x8bit.bitwarden.ui.vault.feature.vault.vaultGraph
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.parcelize.Parcelize
@@ -75,7 +76,7 @@ import kotlinx.parcelize.Parcelize
fun VaultUnlockedNavBarScreen(
viewModel: VaultUnlockedNavBarViewModel = hiltViewModel(),
navController: NavHostController = rememberNavController(),
onNavigateToVaultAddItem: () -> Unit,
onNavigateToVaultAddItem: (VaultItemCipherType) -> Unit,
onNavigateToVaultItem: (vaultItemId: String) -> Unit,
onNavigateToVaultEditItem: (vaultItemId: String) -> Unit,
onNavigateToSearchSend: (searchType: SearchType.Sends) -> Unit,
@@ -160,7 +161,7 @@ private fun VaultUnlockedNavBarScaffold(
sendTabClickedAction: () -> Unit,
generatorTabClickedAction: () -> Unit,
settingsTabClickedAction: () -> Unit,
navigateToVaultAddItem: () -> Unit,
navigateToVaultAddItem: (VaultItemCipherType) -> Unit,
onNavigateToVaultItem: (vaultItemId: String) -> Unit,
onNavigateToVaultEditItem: (vaultItemId: String) -> Unit,
onNavigateToSearchSend: (searchType: SearchType.Sends) -> Unit,

View File

@@ -10,17 +10,23 @@ import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
import com.x8bit.bitwarden.ui.platform.base.util.composableWithSlideTransitions
import com.x8bit.bitwarden.ui.tools.feature.generator.model.GeneratorMode
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
private const val ADD_TYPE: String = "add"
private const val EDIT_TYPE: String = "edit"
private const val CLONE_TYPE: String = "clone"
private const val EDIT_ITEM_ID: String = "vault_edit_id"
private const val ADD_ITEM_TYPE: String = "vault_add_item_type"
private const val ADD_EDIT_ITEM_PREFIX: String = "vault_add_edit_item"
private const val ADD_EDIT_ITEM_TYPE: String = "vault_add_edit_type"
private const val ADD_EDIT_ITEM_ROUTE: String =
"$ADD_EDIT_ITEM_PREFIX/{$ADD_EDIT_ITEM_TYPE}?$EDIT_ITEM_ID={$EDIT_ITEM_ID}"
ADD_EDIT_ITEM_PREFIX +
"/{$ADD_EDIT_ITEM_TYPE}" +
"?$EDIT_ITEM_ID={$EDIT_ITEM_ID}" +
"?$ADD_ITEM_TYPE={$ADD_ITEM_TYPE}"
/**
* Class to retrieve vault add & edit arguments from the [SavedStateHandle].
@@ -31,7 +37,12 @@ data class VaultAddEditArgs(
) {
constructor(savedStateHandle: SavedStateHandle) : this(
vaultAddEditType = when (requireNotNull(savedStateHandle[ADD_EDIT_ITEM_TYPE])) {
ADD_TYPE -> VaultAddEditType.AddItem
ADD_TYPE -> VaultAddEditType.AddItem(
vaultItemCipherType = requireNotNull(
savedStateHandle.get<VaultItemCipherType>(ADD_ITEM_TYPE),
),
)
EDIT_TYPE -> VaultAddEditType.EditItem(requireNotNull(savedStateHandle[EDIT_ITEM_ID]))
CLONE_TYPE -> VaultAddEditType.CloneItem(requireNotNull(savedStateHandle[EDIT_ITEM_ID]))
else -> throw IllegalStateException("Unknown VaultAddEditType.")
@@ -55,6 +66,7 @@ fun NavGraphBuilder.vaultAddEditDestination(
route = ADD_EDIT_ITEM_ROUTE,
arguments = listOf(
navArgument(ADD_EDIT_ITEM_TYPE) { type = NavType.StringType },
navArgument(ADD_ITEM_TYPE) { type = NavType.EnumType(VaultItemCipherType::class.java) },
),
) {
VaultAddEditScreen(
@@ -77,7 +89,8 @@ fun NavController.navigateToVaultAddEdit(
) {
navigate(
route = "$ADD_EDIT_ITEM_PREFIX/${vaultAddEditType.toTypeString()}" +
"?$EDIT_ITEM_ID=${vaultAddEditType.toIdOrNull()}",
"?$EDIT_ITEM_ID=${vaultAddEditType.toIdOrNull()}" +
"?$ADD_ITEM_TYPE=${vaultAddEditType.toVaultItemCipherTypeOrNull()}",
navOptions = navOptions,
)
}
@@ -95,3 +108,11 @@ private fun VaultAddEditType.toIdOrNull(): String? =
is VaultAddEditType.CloneItem -> vaultItemId
is VaultAddEditType.EditItem -> vaultItemId
}
private fun VaultAddEditType.toVaultItemCipherTypeOrNull(): VaultItemCipherType? =
when (this) {
is VaultAddEditType.AddItem -> vaultItemCipherType
is VaultAddEditType.CloneItem,
is VaultAddEditType.EditItem,
-> null
}

View File

@@ -37,6 +37,7 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.model.UriItem
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.toCustomField
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.appendFolderAndOwnerData
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toDefaultAddTypeContent
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toItemType
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toViewState
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.validateCipherOrReturnErrorState
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toCipherView
@@ -111,20 +112,20 @@ class VaultAddEditViewModel @Inject constructor(
null
}
val defaultAddTypeContent = autofillSelectionData
?.toDefaultAddTypeContent(isIndividualVaultDisabled)
?: autofillSaveItem
?.toDefaultAddTypeContent(isIndividualVaultDisabled)
?: VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
isIndividualVaultDisabled = isIndividualVaultDisabled,
type = VaultAddEditState.ViewState.Content.ItemType.Login(),
)
VaultAddEditState(
vaultAddEditType = vaultAddEditType,
viewState = when (vaultAddEditType) {
VaultAddEditType.AddItem -> defaultAddTypeContent
is VaultAddEditType.AddItem -> {
autofillSelectionData
?.toDefaultAddTypeContent(isIndividualVaultDisabled)
?: autofillSaveItem
?.toDefaultAddTypeContent(isIndividualVaultDisabled)
?: VaultAddEditState.ViewState.Content(
common = VaultAddEditState.ViewState.Content.Common(),
isIndividualVaultDisabled = isIndividualVaultDisabled,
type = vaultAddEditType.vaultItemCipherType.toItemType(),
)
}
is VaultAddEditType.EditItem -> VaultAddEditState.ViewState.Loading
is VaultAddEditType.CloneItem -> VaultAddEditState.ViewState.Loading
},
@@ -318,7 +319,7 @@ class VaultAddEditViewModel @Inject constructor(
viewModelScope.launch {
when (val vaultAddEditType = state.vaultAddEditType) {
VaultAddEditType.AddItem -> {
is VaultAddEditType.AddItem -> {
val result = content.createCipherForAddAndCloneItemStates()
sendAction(VaultAddEditAction.Internal.CreateCipherResultReceive(result))
}
@@ -1425,7 +1426,7 @@ data class VaultAddEditState(
*/
val screenDisplayName: Text
get() = when (vaultAddEditType) {
VaultAddEditType.AddItem -> R.string.add_item.asText()
is VaultAddEditType.AddItem -> R.string.add_item.asText()
is VaultAddEditType.EditItem -> R.string.edit_item.asText()
is VaultAddEditType.CloneItem -> R.string.add_item.asText()
}
@@ -1444,7 +1445,7 @@ data class VaultAddEditState(
/**
* Helper to determine if the UI should display the content in add item mode.
*/
val isAddItemMode: Boolean get() = vaultAddEditType == VaultAddEditType.AddItem
val isAddItemMode: Boolean get() = vaultAddEditType is VaultAddEditType.AddItem
/**
* Helper to determine if the UI should display the content in clone mode.

View File

@@ -4,6 +4,8 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.base.util.Text
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.base.util.concat
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditState
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
/**
* Default, "select" Text to show on multi select buttons in the VaultAddEdit package.
@@ -13,3 +15,14 @@ val SELECT_TEXT: Text
.asText()
.concat(R.string.select.asText())
.concat(" --".asText())
/**
* Transforms a [VaultItemCipherType] into [VaultAddEditState.ViewState.Content.ItemType].
*/
fun VaultItemCipherType.toItemType(): VaultAddEditState.ViewState.Content.ItemType =
when (this) {
VaultItemCipherType.LOGIN -> VaultAddEditState.ViewState.Content.ItemType.Login()
VaultItemCipherType.CARD -> VaultAddEditState.ViewState.Content.ItemType.Card()
VaultItemCipherType.IDENTITY -> VaultAddEditState.ViewState.Content.ItemType.Identity()
VaultItemCipherType.SECURE_NOTE -> VaultAddEditState.ViewState.Content.ItemType.SecureNotes
}

View File

@@ -10,6 +10,7 @@ import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
import com.x8bit.bitwarden.ui.platform.base.util.composableWithPushTransitions
import com.x8bit.bitwarden.ui.platform.base.util.composableWithStayTransitions
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType
private const val CARD: String = "card"
@@ -62,7 +63,7 @@ fun NavGraphBuilder.vaultItemListingDestination(
onNavigateToVaultItemScreen: (id: String) -> Unit,
onNavigateToVaultEditItemScreen: (cipherId: String) -> Unit,
onNavigateToVaultItemListing: (vaultItemListingType: VaultItemListingType) -> Unit,
onNavigateToVaultAddItemScreen: () -> Unit,
onNavigateToVaultAddItemScreen: (vaultItemCipherType: VaultItemCipherType) -> Unit,
onNavigateToSearchVault: (searchType: SearchType.Vault) -> Unit,
) {
internalVaultItemListingDestination(
@@ -85,7 +86,7 @@ fun NavGraphBuilder.vaultItemListingDestinationAsRoot(
onNavigateBack: () -> Unit,
onNavigateToVaultItemScreen: (id: String) -> Unit,
onNavigateToVaultEditItemScreen: (cipherId: String) -> Unit,
onNavigateToVaultAddItemScreen: () -> Unit,
onNavigateToVaultAddItemScreen: (VaultItemCipherType) -> Unit,
onNavigateToSearchVault: (searchType: SearchType.Vault) -> Unit,
) {
composableWithStayTransitions(
@@ -144,7 +145,7 @@ private fun NavGraphBuilder.internalVaultItemListingDestination(
onNavigateToVaultItemScreen: (id: String) -> Unit,
onNavigateToVaultEditItemScreen: (cipherId: String) -> Unit,
onNavigateToVaultItemListing: (vaultItemListingType: VaultItemListingType) -> Unit,
onNavigateToVaultAddItemScreen: () -> Unit,
onNavigateToVaultAddItemScreen: (vaultItemCipherType: VaultItemCipherType) -> Unit,
onNavigateToAddSendItem: () -> Unit,
onNavigateToEditSendItem: (sendId: String) -> Unit,
onNavigateToSearch: (searchType: SearchType) -> Unit,

View File

@@ -49,6 +49,7 @@ import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.handlers.VaultItemListingHandlers
import com.x8bit.bitwarden.ui.vault.feature.vault.util.initials
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
@@ -64,7 +65,7 @@ fun VaultItemListingScreen(
onNavigateToVaultItem: (id: String) -> Unit,
onNavigateToVaultEditItemScreen: (cipherVaultId: String) -> Unit,
onNavigateToVaultItemListing: (vaultItemListingType: VaultItemListingType) -> Unit,
onNavigateToVaultAddItemScreen: () -> Unit,
onNavigateToVaultAddItemScreen: (vaultItemCipherType: VaultItemCipherType) -> Unit,
onNavigateToAddSendItem: () -> Unit,
onNavigateToEditSendItem: (sendId: String) -> Unit,
onNavigateToSearch: (searchType: SearchType) -> Unit,
@@ -100,7 +101,7 @@ fun VaultItemListingScreen(
}
is VaultItemListingEvent.NavigateToAddVaultItem -> {
onNavigateToVaultAddItemScreen()
onNavigateToVaultAddItemScreen(event.vaultItemCipherType)
}
is VaultItemListingEvent.NavigateToEditCipher -> {

View File

@@ -38,12 +38,14 @@ import com.x8bit.bitwarden.ui.vault.feature.itemlisting.model.ListingItemOverflo
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.determineListingPredicate
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.toItemListingType
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.toSearchType
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.toVaultItemCipherType
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.toViewState
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.updateWithAdditionalDataIfNecessary
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toAccountSummaries
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toActiveAccountSummary
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toFilteredList
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
@@ -228,9 +230,11 @@ class VaultItemListingViewModel @Inject constructor(
}
private fun handleAddVaultItemClick() {
val event = when (state.itemListingType) {
val event = when (val itemListingType = state.itemListingType) {
is VaultItemListingState.ItemListingType.Vault -> {
VaultItemListingEvent.NavigateToAddVaultItem
VaultItemListingEvent.NavigateToAddVaultItem(
vaultItemCipherType = itemListingType.toVaultItemCipherType(),
)
}
is VaultItemListingState.ItemListingType.Send -> {
@@ -1057,7 +1061,9 @@ sealed class VaultItemListingEvent {
/**
* Navigates to the VaultAddItemScreen.
*/
data object NavigateToAddVaultItem : VaultItemListingEvent()
data class NavigateToAddVaultItem(
val vaultItemCipherType: VaultItemCipherType,
) : VaultItemListingEvent()
/**
* Navigates to the collection.

View File

@@ -2,6 +2,7 @@ package com.x8bit.bitwarden.ui.vault.feature.itemlisting.util
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingState
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
/**
* Transforms a [VaultItemListingState.ItemListingType] into a [SearchType].
@@ -26,3 +27,18 @@ fun VaultItemListingState.ItemListingType.toSearchType(): SearchType =
is VaultItemListingState.ItemListingType.Send.SendFile -> SearchType.Sends.Files
is VaultItemListingState.ItemListingType.Send.SendText -> SearchType.Sends.Texts
}
/**
* Transforms a [VaultItemListingState.ItemListingType.Vault] into a [VaultItemCipherType].
*/
fun VaultItemListingState.ItemListingType.Vault.toVaultItemCipherType(): VaultItemCipherType =
when (this) {
is VaultItemListingState.ItemListingType.Vault.Card -> VaultItemCipherType.CARD
is VaultItemListingState.ItemListingType.Vault.Identity -> VaultItemCipherType.IDENTITY
is VaultItemListingState.ItemListingType.Vault.SecureNote -> VaultItemCipherType.SECURE_NOTE
is VaultItemListingState.ItemListingType.Vault.Login -> VaultItemCipherType.LOGIN
is VaultItemListingState.ItemListingType.Vault.Trash,
is VaultItemListingState.ItemListingType.Vault.Collection,
is VaultItemListingState.ItemListingType.Vault.Folder,
-> throw IllegalStateException("Cannot create vault item from this VaultItemListingState!")
}

View File

@@ -9,6 +9,7 @@ import com.x8bit.bitwarden.ui.vault.feature.itemlisting.navigateToVaultItemListi
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.vaultItemListingDestination
import com.x8bit.bitwarden.ui.vault.feature.verificationcode.navigateToVerificationCodeScreen
import com.x8bit.bitwarden.ui.vault.feature.verificationcode.vaultVerificationCodeDestination
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
const val VAULT_GRAPH_ROUTE: String = "vault_graph"
@@ -18,7 +19,7 @@ const val VAULT_GRAPH_ROUTE: String = "vault_graph"
@Suppress("LongParameterList")
fun NavGraphBuilder.vaultGraph(
navController: NavController,
onNavigateToVaultAddItemScreen: () -> Unit,
onNavigateToVaultAddItemScreen: (vaultItemCipherType: VaultItemCipherType) -> Unit,
onNavigateToVaultItemScreen: (vaultItemId: String) -> Unit,
onNavigateToVaultEditItemScreen: (vaultItemId: String) -> Unit,
onNavigateToSearchVault: (searchType: SearchType.Vault) -> Unit,
@@ -29,7 +30,9 @@ fun NavGraphBuilder.vaultGraph(
startDestination = VAULT_ROUTE,
) {
vaultDestination(
onNavigateToVaultAddItemScreen = onNavigateToVaultAddItemScreen,
onNavigateToVaultAddItemScreen = {
onNavigateToVaultAddItemScreen(VaultItemCipherType.LOGIN)
},
onNavigateToVaultItemScreen = onNavigateToVaultItemScreen,
onNavigateToVaultEditItemScreen = onNavigateToVaultEditItemScreen,
onNavigateToVaultItemListingScreen = { navController.navigateToVaultItemListing(it) },

View File

@@ -15,9 +15,13 @@ sealed class VaultAddEditType : Parcelable {
/**
* Indicates that we want to create a completely new vault item.
*
* @property vaultItemCipherType The specified [VaultItemCipherType].
*/
@Parcelize
data object AddItem : VaultAddEditType() {
data class AddItem(
val vaultItemCipherType: VaultItemCipherType,
) : VaultAddEditType() {
override val vaultItemId: String?
get() = null
}

View File

@@ -0,0 +1,27 @@
package com.x8bit.bitwarden.ui.vault.model
/**
* Represents different types of ciphers that can be added/viewed.
*/
enum class VaultItemCipherType {
/**
* A login cipher.
*/
LOGIN,
/**
* A card cipher.
*/
CARD,
/**
* A identity cipher.
*/
IDENTITY,
/**
* A secure note cipher.
*/
SECURE_NOTE,
}