diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt index 33b82df592..368344edb3 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt @@ -50,7 +50,6 @@ private const val AUTH_CODE_SPACING_INTERVAL = 3 fun VaultItemLoginContent( commonState: VaultItemState.ViewState.Content.Common, loginItemState: VaultItemState.ViewState.Content.ItemType.Login, - totpCodeItemData: TotpCodeItemData?, vaultCommonItemTypeHandlers: VaultCommonItemTypeHandlers, vaultLoginItemTypeHandlers: VaultLoginItemTypeHandlers, modifier: Modifier = Modifier, @@ -137,7 +136,7 @@ fun VaultItemLoginContent( } } - totpCodeItemData?.let { totpCodeItemData -> + loginItemState.totpCodeItemData?.let { totpCodeItemData -> item(key = "totpCode") { Spacer(modifier = Modifier.height(8.dp)) TotpField( @@ -423,7 +422,7 @@ private fun PasswordField( private fun TotpField( totpCodeItemData: TotpCodeItemData, enabled: Boolean, - onCopyTotpClick: (String) -> Unit, + onCopyTotpClick: () -> Unit, onAuthenticatorHelpToolTipClick: () -> Unit, modifier: Modifier = Modifier, ) { @@ -449,7 +448,7 @@ private fun TotpField( BitwardenStandardIconButton( vectorIconRes = R.drawable.ic_copy, contentDescription = stringResource(id = R.string.copy_totp), - onClick = { onCopyTotpClick(totpCodeItemData.totpCode) }, + onClick = onCopyTotpClick, modifier = Modifier.testTag(tag = "LoginCopyTotpButton"), ) }, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt index 5ed3540c21..f5fdf71b88 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt @@ -45,7 +45,6 @@ import com.x8bit.bitwarden.ui.vault.feature.item.handlers.VaultCommonItemTypeHan import com.x8bit.bitwarden.ui.vault.feature.item.handlers.VaultIdentityItemTypeHandlers import com.x8bit.bitwarden.ui.vault.feature.item.handlers.VaultLoginItemTypeHandlers import com.x8bit.bitwarden.ui.vault.feature.item.handlers.VaultSshKeyItemTypeHandlers -import com.x8bit.bitwarden.ui.vault.feature.item.model.TotpCodeItemData import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType /** @@ -261,7 +260,6 @@ fun VaultItemScreen( ) { VaultItemContent( viewState = state.viewState, - totpCodeItemData = state.totpCodeItemData, modifier = Modifier .fillMaxSize(), vaultCommonItemTypeHandlers = remember(viewModel) { @@ -352,7 +350,6 @@ private fun VaultItemDialogs( @Composable private fun VaultItemContent( viewState: VaultItemState.ViewState, - totpCodeItemData: TotpCodeItemData?, vaultCommonItemTypeHandlers: VaultCommonItemTypeHandlers, vaultLoginItemTypeHandlers: VaultLoginItemTypeHandlers, vaultCardItemTypeHandlers: VaultCardItemTypeHandlers, @@ -373,7 +370,6 @@ private fun VaultItemContent( VaultItemLoginContent( commonState = viewState.common, loginItemState = viewState.type, - totpCodeItemData = totpCodeItemData, vaultCommonItemTypeHandlers = vaultCommonItemTypeHandlers, vaultLoginItemTypeHandlers = vaultLoginItemTypeHandlers, modifier = modifier, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt index dfafbcb27f..d98bb42bc9 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt @@ -78,7 +78,6 @@ class VaultItemViewModel @Inject constructor( vaultItemId = args.vaultItemId, cipherType = args.cipherType, viewState = VaultItemState.ViewState.Loading, - totpCodeItemData = null, dialog = null, baseIconUrl = environmentRepository.environment.environmentUrlData.baseIconUrl, isIconLoadingDisabled = settingsRepository.isIconLoadingDisabled, @@ -102,16 +101,26 @@ class VaultItemViewModel @Inject constructor( combine( vaultRepository.getVaultItemStateFlow(state.vaultItemId), authRepository.userStateFlow, + vaultRepository.getAuthCodeFlow(state.vaultItemId), vaultRepository.collectionsStateFlow, vaultRepository.foldersStateFlow, - ) { cipherViewState, userState, collectionsState, folderState -> + ) { cipherViewState, userState, authCodeState, collectionsState, folderState -> + val totpCodeData = authCodeState.data?.let { + TotpCodeItemData( + periodSeconds = it.periodSeconds, + timeLeftSeconds = it.timeLeftSeconds, + totpCode = it.totpCode, + verificationCode = it.code, + ) + } VaultItemAction.Internal.VaultDataReceive( userState = userState, vaultDataState = combineDataStates( cipherViewState, + authCodeState, collectionsState, folderState, - ) { _, _, _ -> + ) { _, _, _, _ -> // We are only combining the DataStates to know the overall state, // we map it to the appropriate value below. } @@ -156,6 +165,7 @@ class VaultItemViewModel @Inject constructor( VaultItemStateData( cipher = cipherView, + totpCodeItemData = totpCodeData, canDelete = canDelete, canAssociateToCollections = canAssignToCollections, canEdit = canEdit, @@ -171,21 +181,6 @@ class VaultItemViewModel @Inject constructor( .map { VaultItemAction.Internal.IsIconLoadingDisabledUpdateReceive(it) } .onEach(::sendAction) .launchIn(viewModelScope) - - vaultRepository.getAuthCodeFlow(state.vaultItemId) - .map { - VaultItemAction.Internal.TotpDataReceive( - totpData = TotpCodeItemData( - periodSeconds = it.data?.periodSeconds ?: 0, - timeLeftSeconds = it.data?.timeLeftSeconds ?: 0, - totpCode = it.data?.totpCode ?: "", - verificationCode = it.data?.code ?: "", - ) - ) - } - .onEach(::sendAction) - .launchIn(viewModelScope) - } override fun handleAction(action: VaultItemAction) { @@ -607,7 +602,7 @@ class VaultItemViewModel @Inject constructor( } is VaultItemAction.ItemType.Login.CopyTotpClick -> { - handleCopyTotpClick(action) + handleCopyTotpClick() } is VaultItemAction.ItemType.Login.CopyUriClick -> { @@ -668,11 +663,14 @@ class VaultItemViewModel @Inject constructor( } } - private fun handleCopyTotpClick(action: VaultItemAction.ItemType.Login.CopyTotpClick) { - clipboardManager.setText( - text = action.code, - toastDescriptorOverride = R.string.totp.asText(), - ) + private fun handleCopyTotpClick() { + onLoginContent { _, login -> + val code = login.totpCodeItemData?.verificationCode ?: return@onLoginContent + clipboardManager.setText( + text = code, + toastDescriptorOverride = R.string.totp.asText(), + ) + } } private fun handleCopyUriClick(action: VaultItemAction.ItemType.Login.CopyUriClick) { @@ -1095,10 +1093,6 @@ class VaultItemViewModel @Inject constructor( is VaultItemAction.Internal.IsIconLoadingDisabledUpdateReceive -> { handleIsIconLoadingDisabledUpdateReceive(action) } - - is VaultItemAction.Internal.TotpDataReceive -> { - handleTotpDataReceive(action) - } } } @@ -1204,6 +1198,7 @@ class VaultItemViewModel @Inject constructor( previousState = state.viewState.asContentOrNull(), isPremiumUser = account.isPremium, hasMasterPassword = account.hasMasterPassword, + totpCodeItemData = this.data?.totpCodeItemData, canDelete = this.data?.canDelete == true, canAssignToCollections = this.data?.canAssociateToCollections == true, canEdit = this.data?.canEdit == true, @@ -1358,12 +1353,6 @@ class VaultItemViewModel @Inject constructor( mutableStateFlow.update { it.copy(isIconLoadingDisabled = action.isDisabled) } } - private fun handleTotpDataReceive( - action: VaultItemAction.Internal.TotpDataReceive, - ) { - mutableStateFlow.update { it.copy(totpCodeItemData = action.totpData) } - } - //endregion Internal Type Handlers private fun updateDialogState(dialog: VaultItemState.DialogState?) { @@ -1451,7 +1440,6 @@ data class VaultItemState( val vaultItemId: String, val cipherType: VaultItemCipherType, val viewState: ViewState, - val totpCodeItemData: TotpCodeItemData?, val dialog: DialogState?, val baseIconUrl: String, val isIconLoadingDisabled: Boolean, @@ -1609,11 +1597,14 @@ data class VaultItemState( * Represents a custom field, TextField, HiddenField, BooleanField, or LinkedField. */ sealed class Custom : Parcelable { + abstract val id: String + /** * Represents the data for displaying a custom text field. */ @Parcelize data class TextField( + override val id: String, val name: String, val value: String, val isCopyable: Boolean, @@ -1624,6 +1615,7 @@ data class VaultItemState( */ @Parcelize data class HiddenField( + override val id: String, val name: String, val value: String, val isCopyable: Boolean, @@ -1635,6 +1627,7 @@ data class VaultItemState( */ @Parcelize data class BooleanField( + override val id: String, val name: String, val value: Boolean, ) : Custom() @@ -1644,6 +1637,7 @@ data class VaultItemState( */ @Parcelize data class LinkedField( + override val id: String, val vaultLinkedFieldType: VaultLinkedFieldType, val name: String, ) : Custom() @@ -1684,6 +1678,7 @@ data class VaultItemState( val passwordData: PasswordData?, val uris: List, val passwordRevisionDate: String?, + val totpCodeItemData: TotpCodeItemData?, val isPremiumUser: Boolean, val canViewTotpCode: Boolean, val fido2CredentialCreationDateText: Text?, @@ -1695,8 +1690,10 @@ data class VaultItemState( val hasLoginCredentials: Boolean get() = username != null || passwordData != null || + totpCodeItemData != null || fido2CredentialCreationDateText != null + /** * A wrapper for the password data. * @@ -2136,9 +2133,7 @@ sealed class VaultItemAction { /** * The user has clicked the copy button for the TOTP code. */ - data class CopyTotpClick( - val code: String, - ) : Login() + data object CopyTotpClick : Login() /** * The user has clicked the copy button for a URI. @@ -2296,10 +2291,6 @@ sealed class VaultItemAction { val vaultDataState: DataState, ) : Internal() - data class TotpDataReceive( - val totpData: TotpCodeItemData?, - ) : Internal() - /** * Indicates that the verify password result has been received. */ diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/handlers/VaultLoginItemTypeHandlers.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/handlers/VaultLoginItemTypeHandlers.kt index a5188192b9..a6c37500ca 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/handlers/VaultLoginItemTypeHandlers.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/handlers/VaultLoginItemTypeHandlers.kt @@ -11,7 +11,7 @@ import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemViewModel data class VaultLoginItemTypeHandlers( val onCheckForBreachClick: () -> Unit, val onCopyPasswordClick: () -> Unit, - val onCopyTotpCodeClick: (String) -> Unit, + val onCopyTotpCodeClick: () -> Unit, val onAuthenticatorHelpToolTipClick: () -> Unit, val onCopyUriClick: (String) -> Unit, val onCopyUsernameClick: () -> Unit, @@ -35,7 +35,7 @@ data class VaultLoginItemTypeHandlers( viewModel.trySendAction(VaultItemAction.ItemType.Login.CopyPasswordClick) }, onCopyTotpCodeClick = { - viewModel.trySendAction(VaultItemAction.ItemType.Login.CopyTotpClick(it)) + viewModel.trySendAction(VaultItemAction.ItemType.Login.CopyTotpClick) }, onAuthenticatorHelpToolTipClick = { viewModel.trySendAction( diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/model/VaultItemStateData.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/model/VaultItemStateData.kt index 60a9b6d739..862e81c1b0 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/model/VaultItemStateData.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/model/VaultItemStateData.kt @@ -7,6 +7,7 @@ import kotlinx.collections.immutable.ImmutableList * The state containing totp code item information and the cipher for the item. * * @property cipher The cipher view for the item. + * @property totpCodeItemData The data for the totp code. * @property canDelete Whether the item can be deleted. * @property canAssociateToCollections Whether the item can be associated to a collection. * @property canEdit Whether the item can be edited. @@ -14,6 +15,7 @@ import kotlinx.collections.immutable.ImmutableList */ data class VaultItemStateData( val cipher: CipherView?, + val totpCodeItemData: TotpCodeItemData?, val canDelete: Boolean, val canAssociateToCollections: Boolean, val canEdit: Boolean, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt index 9a7d6e1f86..0ca2da8bae 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt @@ -42,6 +42,7 @@ fun CipherView.toViewState( previousState: VaultItemState.ViewState.Content?, isPremiumUser: Boolean, hasMasterPassword: Boolean, + totpCodeItemData: TotpCodeItemData?, clock: Clock = Clock.systemDefaultZone(), canDelete: Boolean, canAssignToCollections: Boolean, @@ -56,7 +57,14 @@ fun CipherView.toViewState( name = name, requiresReprompt = (reprompt == CipherRepromptType.PASSWORD && hasMasterPassword) && previousState?.common?.requiresReprompt != false, - customFields = fields.orEmpty().map { it.toCustomField() }, + customFields = fields.orEmpty().map { fieldView -> + fieldView.toCustomField( + previousState = previousState + ?.common + ?.customFields + ?.find { it.id == fieldView.hashCode().toString() }, + ) + }, lastUpdated = revisionDate.toFormattedPattern( pattern = LAST_UPDATED_DATE_TIME_PATTERN, clock = clock, @@ -124,6 +132,7 @@ fun CipherView.toViewState( ), isPremiumUser = isPremiumUser, canViewTotpCode = isPremiumUser || this.organizationUseTotp, + totpCodeItemData = totpCodeItemData, fido2CredentialCreationDateText = loginValues .fido2Credentials ?.firstOrNull() @@ -193,27 +202,40 @@ fun CipherView.toViewState( }, ) -private fun FieldView.toCustomField(): VaultItemState.ViewState.Content.Common.Custom = + +/** + * Transforms [FieldView] into [VaultItemState.ViewState.Content.Common.Custom]. + */ +fun FieldView.toCustomField( + previousState: VaultItemState.ViewState.Content.Common.Custom?, +): VaultItemState.ViewState.Content.Common.Custom = when (type) { FieldType.TEXT -> VaultItemState.ViewState.Content.Common.Custom.TextField( + id = this.hashCode().toString(), name = name.orEmpty(), value = value.orZeroWidthSpace(), isCopyable = !value.isNullOrBlank(), ) FieldType.HIDDEN -> VaultItemState.ViewState.Content.Common.Custom.HiddenField( + id = this.hashCode().toString(), name = name.orEmpty(), value = value.orZeroWidthSpace(), isCopyable = !value.isNullOrBlank(), - isVisible = false, + isVisible = (previousState as? + VaultItemState.ViewState.Content.Common.Custom.HiddenField) + ?.isVisible + ?: false, ) FieldType.BOOLEAN -> VaultItemState.ViewState.Content.Common.Custom.BooleanField( + id = this.hashCode().toString(), name = name.orEmpty(), value = value?.toBoolean() ?: false, ) FieldType.LINKED -> VaultItemState.ViewState.Content.Common.Custom.LinkedField( + id = this.hashCode().toString(), vaultLinkedFieldType = VaultLinkedFieldType.fromId(requireNotNull(linkedId)), name = name.orEmpty(), ) diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt index aa5a871012..8e6e5927ac 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt @@ -776,6 +776,7 @@ class VaultItemScreenTest : BaseComposeTest() { @Test fun `on show hidden field click should send HiddenFieldVisibilityClicked`() { val textField = VaultItemState.ViewState.Content.Common.Custom.HiddenField( + id = "12345", name = "hidden", value = "hidden password", isCopyable = true, @@ -814,6 +815,7 @@ class VaultItemScreenTest : BaseComposeTest() { @Test fun `copy hidden field button should be displayed according to state`() { val hiddenField = VaultItemState.ViewState.Content.Common.Custom.HiddenField( + id = "12345", name = "hidden", value = "hidden password", isCopyable = true, @@ -855,6 +857,7 @@ class VaultItemScreenTest : BaseComposeTest() { @Test fun `on copy hidden field click should send CopyCustomHiddenFieldClick`() { val hiddenField = VaultItemState.ViewState.Content.Common.Custom.HiddenField( + id = "12345", name = "hidden", value = "hidden password", isCopyable = true, @@ -890,6 +893,7 @@ class VaultItemScreenTest : BaseComposeTest() { @Test fun `on copy text field click should send CopyCustomTextFieldClick`() { val textField = VaultItemState.ViewState.Content.Common.Custom.TextField( + id = "12345", name = "text", value = "value", isCopyable = true, @@ -924,6 +928,7 @@ class VaultItemScreenTest : BaseComposeTest() { @Test fun `text field copy button should be displayed according to state`() { val textField = VaultItemState.ViewState.Content.Common.Custom.TextField( + id = "12345", name = "text", value = "value", isCopyable = true, @@ -1552,6 +1557,7 @@ class VaultItemScreenTest : BaseComposeTest() { // Adding a custom field so that we can scroll to it // So we can see the Copy notes button but not have it covered by the FAB val textField = VaultItemState.ViewState.Content.Common.Custom.TextField( + id = "12345", name = "text", value = "value", isCopyable = true, @@ -1587,6 +1593,7 @@ class VaultItemScreenTest : BaseComposeTest() { // Adding a custom field so that we can scroll to it // So we can see the Copy notes button but not have it covered by the FAB val textField = VaultItemState.ViewState.Content.Common.Custom.TextField( + id = "12345", name = "text", value = "value", isCopyable = true, @@ -1642,6 +1649,7 @@ class VaultItemScreenTest : BaseComposeTest() { // Adding a custom field so that we can scroll to it // So we can see the Copy notes button but not have it covered by the FAB val textField = VaultItemState.ViewState.Content.Common.Custom.TextField( + id = "12345", name = "text", value = "value", isCopyable = true, @@ -1885,11 +1893,13 @@ class VaultItemScreenTest : BaseComposeTest() { fun `in login state, linked custom fields should be displayed according to state`() { val linkedFieldUserName = VaultItemState.ViewState.Content.Common.Custom.LinkedField( + id = "12345", name = "linked username", vaultLinkedFieldType = VaultLinkedFieldType.USERNAME, ) val linkedFieldsPassword = VaultItemState.ViewState.Content.Common.Custom.LinkedField( + id = "12345", name = "linked password", vaultLinkedFieldType = VaultLinkedFieldType.PASSWORD, ) @@ -3149,17 +3159,20 @@ private val DEFAULT_COMMON: VaultItemState.ViewState.Content.Common = notes = "Lots of notes", customFields = listOf( VaultItemState.ViewState.Content.Common.Custom.TextField( + id = "12345", name = "text", value = "value", isCopyable = true, ), VaultItemState.ViewState.Content.Common.Custom.HiddenField( + id = "12345", name = "hidden", value = "hidden password", isCopyable = true, isVisible = false, ), VaultItemState.ViewState.Content.Common.Custom.BooleanField( + id = "12345", name = "boolean", value = true, ), diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt index 2626eff14e..3fa09f27b5 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt @@ -1070,6 +1070,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { runTest { val loginState = DEFAULT_STATE.copy(viewState = DEFAULT_VIEW_STATE) val field = VaultItemState.ViewState.Content.Common.Custom.HiddenField( + id = "12345", name = "hidden", value = "value", isCopyable = true, @@ -1135,6 +1136,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { runTest { val hiddenField = VaultItemState.ViewState.Content.Common.Custom.HiddenField( + id = "12345", name = "hidden", value = "value", isCopyable = true, @@ -3702,25 +3704,30 @@ class VaultItemViewModelTest : BaseViewModelTest() { notes = "Lots of notes", customFields = listOf( VaultItemState.ViewState.Content.Common.Custom.TextField( + id = "12345", name = "text", value = "value", isCopyable = true, ), VaultItemState.ViewState.Content.Common.Custom.HiddenField( + id = "12345", name = "hidden", value = "value", isCopyable = true, isVisible = false, ), VaultItemState.ViewState.Content.Common.Custom.BooleanField( + id = "12345", name = "boolean", value = true, ), VaultItemState.ViewState.Content.Common.Custom.LinkedField( + id = "12345", name = "linked username", vaultLinkedFieldType = VaultLinkedFieldType.USERNAME, ), VaultItemState.ViewState.Content.Common.Custom.LinkedField( + id = "12345", name = "linked password", vaultLinkedFieldType = VaultLinkedFieldType.PASSWORD, ), diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/util/VaultItemTestUtil.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/util/VaultItemTestUtil.kt index 99e45ba59d..0f0c9cc6b0 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/util/VaultItemTestUtil.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/util/VaultItemTestUtil.kt @@ -18,7 +18,6 @@ import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.model.IconData import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemState import com.x8bit.bitwarden.ui.vault.feature.item.model.TotpCodeItemData -import com.x8bit.bitwarden.ui.vault.model.VaultLinkedFieldType import kotlinx.collections.immutable.persistentListOf import java.time.Instant @@ -188,29 +187,36 @@ fun createCommonContent( lastUpdated = "1/1/70 12:16 AM", notes = "Lots of notes", customFields = listOf( - VaultItemState.ViewState.Content.Common.Custom.TextField( + FieldView( name = "text", value = "value", - isCopyable = true, - ), - VaultItemState.ViewState.Content.Common.Custom.HiddenField( + type = FieldType.TEXT, + linkedId = null, + ).toCustomField(null), + FieldView( name = "hidden", value = "value", - isCopyable = true, - isVisible = false, - ), - VaultItemState.ViewState.Content.Common.Custom.BooleanField( + type = FieldType.HIDDEN, + linkedId = null, + ).toCustomField(null), + FieldView( name = "boolean", - value = true, - ), - VaultItemState.ViewState.Content.Common.Custom.LinkedField( + value = "true", + type = FieldType.BOOLEAN, + linkedId = null, + ).toCustomField(null), + FieldView( name = "linked username", - vaultLinkedFieldType = VaultLinkedFieldType.USERNAME, - ), - VaultItemState.ViewState.Content.Common.Custom.LinkedField( + value = null, + type = FieldType.LINKED, + linkedId = 100U, + ).toCustomField(null), + FieldView( name = "linked password", - vaultLinkedFieldType = VaultLinkedFieldType.PASSWORD, - ), + value = null, + type = FieldType.LINKED, + linkedId = 101U, + ).toCustomField(null), ), requiresReprompt = true, requiresCloneConfirmation = true,