mirror of
https://github.com/bitwarden/android.git
synced 2026-08-26 22:04:07 -05:00
[PM-32808] feat: Add Add/Edit support for Driver's License item type (#6908)
This commit is contained in:
+8
-1
@@ -36,6 +36,7 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditBankAcc
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCardTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCommonHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditIdentityTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLicenseTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLoginTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditSshKeyTypeHandlers
|
||||
|
||||
@@ -54,6 +55,7 @@ fun CoachMarkScope<AddEditItemCoachMark>.VaultAddEditContent(
|
||||
cardItemTypeHandlers: VaultAddEditCardTypeHandlers,
|
||||
sshKeyItemTypeHandlers: VaultAddEditSshKeyTypeHandlers,
|
||||
bankAccountItemTypeHandlers: VaultAddEditBankAccountTypeHandlers,
|
||||
licenseItemTypeHandlers: VaultAddEditLicenseTypeHandlers,
|
||||
isCardScannerEnabled: Boolean,
|
||||
cardHolderNameFocusRequester: FocusRequester,
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -288,7 +290,12 @@ fun CoachMarkScope<AddEditItemCoachMark>.VaultAddEditContent(
|
||||
)
|
||||
}
|
||||
|
||||
is VaultAddEditState.ViewState.Content.ItemType.License -> Unit
|
||||
is VaultAddEditState.ViewState.Content.ItemType.License -> {
|
||||
vaultAddEditLicenseItems(
|
||||
licenseState = state.type,
|
||||
licenseHandlers = licenseItemTypeHandlers,
|
||||
)
|
||||
}
|
||||
is VaultAddEditState.ViewState.Content.ItemType.Passport -> Unit
|
||||
}
|
||||
|
||||
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
package com.x8bit.bitwarden.ui.vault.feature.addedit
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.bitwarden.ui.platform.base.util.standardHorizontalMargin
|
||||
import com.bitwarden.ui.platform.components.button.BitwardenTextSelectionButton
|
||||
import com.bitwarden.ui.platform.components.field.BitwardenPasswordField
|
||||
import com.bitwarden.ui.platform.components.field.BitwardenTextField
|
||||
import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText
|
||||
import com.bitwarden.ui.platform.components.model.CardStyle
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLicenseTypeHandlers
|
||||
|
||||
/**
|
||||
* The UI for adding and editing a license cipher.
|
||||
*/
|
||||
@Suppress("LongMethod")
|
||||
fun LazyListScope.vaultAddEditLicenseItems(
|
||||
licenseState: VaultAddEditState.ViewState.Content.ItemType.License,
|
||||
licenseHandlers: VaultAddEditLicenseTypeHandlers,
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
BitwardenListHeaderText(
|
||||
label = stringResource(id = BitwardenString.license_details),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.first_name),
|
||||
value = licenseState.firstName,
|
||||
onValueChange = licenseHandlers.onFirstNameTextChange,
|
||||
textFieldTestTag = "LicenseFirstNameEntry",
|
||||
cardStyle = CardStyle.Top(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.middle_name),
|
||||
value = licenseState.middleName,
|
||||
onValueChange = licenseHandlers.onMiddleNameTextChange,
|
||||
textFieldTestTag = "LicenseMiddleNameEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.last_name),
|
||||
value = licenseState.lastName,
|
||||
onValueChange = licenseHandlers.onLastNameTextChange,
|
||||
textFieldTestTag = "LicenseLastNameEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenPasswordField(
|
||||
label = stringResource(id = BitwardenString.license_number),
|
||||
value = licenseState.licenseNumber,
|
||||
onValueChange = licenseHandlers.onLicenseNumberTextChange,
|
||||
passwordFieldTestTag = "LicenseLicenseNumberEntry",
|
||||
showPasswordTestTag = "LicenseShowLicenseNumberButton",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextSelectionButton(
|
||||
label = stringResource(id = BitwardenString.date_of_birth),
|
||||
selectedOption = licenseState.dateOfBirth,
|
||||
// TODO: Open a native Material date picker (separate ticket TBD).
|
||||
onClick = {},
|
||||
textFieldTestTag = "LicenseDateOfBirthEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.issuing_country),
|
||||
value = licenseState.issuingCountry,
|
||||
onValueChange = licenseHandlers.onIssuingCountryTextChange,
|
||||
textFieldTestTag = "LicenseIssuingCountryEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.issuing_state),
|
||||
value = licenseState.issuingState,
|
||||
onValueChange = licenseHandlers.onIssuingStateTextChange,
|
||||
textFieldTestTag = "LicenseIssuingStateEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.issuing_authority),
|
||||
value = licenseState.issuingAuthority,
|
||||
onValueChange = licenseHandlers.onIssuingAuthorityTextChange,
|
||||
textFieldTestTag = "LicenseIssuingAuthorityEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextSelectionButton(
|
||||
label = stringResource(id = BitwardenString.issue_date),
|
||||
selectedOption = licenseState.issueDate,
|
||||
// TODO: Open a native Material date picker (separate ticket TBD).
|
||||
onClick = {},
|
||||
textFieldTestTag = "LicenseIssueDateEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextSelectionButton(
|
||||
label = stringResource(id = BitwardenString.expiration_date),
|
||||
selectedOption = licenseState.expirationDate,
|
||||
// TODO: Open a native Material date picker (separate ticket TBD).
|
||||
onClick = {},
|
||||
textFieldTestTag = "LicenseExpirationDateEntry",
|
||||
cardStyle = CardStyle.Middle(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = BitwardenString.license_class),
|
||||
value = licenseState.licenseClass,
|
||||
onValueChange = licenseHandlers.onLicenseClassTextChange,
|
||||
textFieldTestTag = "LicenseLicenseClassEntry",
|
||||
cardStyle = CardStyle.Bottom,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,7 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditBankAcc
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCardTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCommonHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditIdentityTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLicenseTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLoginTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditSshKeyTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditUserVerificationHandlers
|
||||
@@ -241,6 +242,10 @@ fun VaultAddEditScreen(
|
||||
VaultAddEditBankAccountTypeHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
|
||||
val licenseItemTypeHandlers = remember(viewModel) {
|
||||
VaultAddEditLicenseTypeHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
|
||||
val archiveClickAction = { viewModel.trySendAction(VaultAddEditAction.Common.ArchiveClick) }
|
||||
|
||||
val unarchiveClickAction = { viewModel.trySendAction(VaultAddEditAction.Common.UnarchiveClick) }
|
||||
@@ -423,6 +428,7 @@ fun VaultAddEditScreen(
|
||||
cardItemTypeHandlers = cardItemTypeHandlers,
|
||||
sshKeyItemTypeHandlers = sshKeyItemTypeHandlers,
|
||||
bankAccountItemTypeHandlers = bankAccountItemTypeHandlers,
|
||||
licenseItemTypeHandlers = licenseItemTypeHandlers,
|
||||
isCardScannerEnabled = state.isCardScannerEnabled,
|
||||
cardHolderNameFocusRequester = cardHolderNameFocusRequester,
|
||||
lazyListState = lazyListState,
|
||||
|
||||
+107
-4
@@ -314,6 +314,10 @@ class VaultAddEditViewModel @Inject constructor(
|
||||
handleBankAccountTypeActions(action)
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.LicenseType -> {
|
||||
handleLicenseTypeActions(action)
|
||||
}
|
||||
|
||||
is VaultAddEditAction.Internal -> handleInternalActions(action)
|
||||
}
|
||||
}
|
||||
@@ -1746,6 +1750,49 @@ class VaultAddEditViewModel @Inject constructor(
|
||||
|
||||
//endregion Bank Account Type Handlers
|
||||
|
||||
//region License Type Handlers
|
||||
|
||||
@Suppress("LongMethod")
|
||||
private fun handleLicenseTypeActions(
|
||||
action: VaultAddEditAction.ItemType.LicenseType,
|
||||
) {
|
||||
when (action) {
|
||||
is VaultAddEditAction.ItemType.LicenseType.FirstNameTextChange -> {
|
||||
updateLicenseContent { it.copy(firstName = action.firstName) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.LicenseType.MiddleNameTextChange -> {
|
||||
updateLicenseContent { it.copy(middleName = action.middleName) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.LicenseType.LastNameTextChange -> {
|
||||
updateLicenseContent { it.copy(lastName = action.lastName) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.LicenseType.LicenseNumberTextChange -> {
|
||||
updateLicenseContent { it.copy(licenseNumber = action.licenseNumber) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.LicenseType.IssuingCountryTextChange -> {
|
||||
updateLicenseContent { it.copy(issuingCountry = action.country) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.LicenseType.IssuingStateTextChange -> {
|
||||
updateLicenseContent { it.copy(issuingState = action.state) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.LicenseType.IssuingAuthorityTextChange -> {
|
||||
updateLicenseContent { it.copy(issuingAuthority = action.authority) }
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.LicenseType.LicenseClassTextChange -> {
|
||||
updateLicenseContent { it.copy(licenseClass = action.licenseClass) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion License Type Handlers
|
||||
|
||||
//region Internal Type Handlers
|
||||
|
||||
private fun handleInternalActions(action: VaultAddEditAction.Internal) {
|
||||
@@ -2513,6 +2560,16 @@ class VaultAddEditViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun updateLicenseContent(
|
||||
crossinline block: (VaultAddEditState.ViewState.Content.ItemType.License) ->
|
||||
VaultAddEditState.ViewState.Content.ItemType.License,
|
||||
) {
|
||||
updateContent { currentContent ->
|
||||
(currentContent.type as? VaultAddEditState.ViewState.Content.ItemType.License)
|
||||
?.let { currentContent.copy(type = block(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
private suspend fun VaultAddEditState.ViewState.Content.createCipherForAddAndCloneItemStates(): CreateCipherResult {
|
||||
return common.selectedOwner?.collections
|
||||
@@ -2619,7 +2676,7 @@ data class VaultAddEditState(
|
||||
VaultItemCipherType.SECURE_NOTE -> BitwardenString.new_note.asText()
|
||||
VaultItemCipherType.SSH_KEY -> BitwardenString.new_ssh_key.asText()
|
||||
VaultItemCipherType.BANK_ACCOUNT -> BitwardenString.new_bank_account.asText()
|
||||
VaultItemCipherType.DRIVERS_LICENSE -> BitwardenString.new_drivers_license.asText()
|
||||
VaultItemCipherType.DRIVERS_LICENSE -> BitwardenString.new_license.asText()
|
||||
VaultItemCipherType.PASSPORT -> BitwardenString.new_passport.asText()
|
||||
}
|
||||
|
||||
@@ -2630,7 +2687,7 @@ data class VaultAddEditState(
|
||||
VaultItemCipherType.SECURE_NOTE -> BitwardenString.edit_note.asText()
|
||||
VaultItemCipherType.SSH_KEY -> BitwardenString.edit_ssh_key.asText()
|
||||
VaultItemCipherType.BANK_ACCOUNT -> BitwardenString.edit_bank_account.asText()
|
||||
VaultItemCipherType.DRIVERS_LICENSE -> BitwardenString.edit_drivers_license.asText()
|
||||
VaultItemCipherType.DRIVERS_LICENSE -> BitwardenString.edit_license.asText()
|
||||
VaultItemCipherType.PASSPORT -> BitwardenString.edit_passport.asText()
|
||||
}
|
||||
}
|
||||
@@ -2724,7 +2781,7 @@ data class VaultAddEditState(
|
||||
SECURE_NOTES(BitwardenString.type_secure_note),
|
||||
SSH_KEYS(BitwardenString.type_ssh_key),
|
||||
BANK_ACCOUNT(BitwardenString.type_bank_account),
|
||||
DRIVERS_LICENSE(BitwardenString.type_license),
|
||||
LICENSE(BitwardenString.type_license),
|
||||
PASSPORT(BitwardenString.type_passport),
|
||||
}
|
||||
|
||||
@@ -3067,7 +3124,7 @@ data class VaultAddEditState(
|
||||
val licenseClass: String = "",
|
||||
) : ItemType() {
|
||||
override val itemTypeOption: ItemTypeOption
|
||||
get() = ItemTypeOption.DRIVERS_LICENSE
|
||||
get() = ItemTypeOption.LICENSE
|
||||
|
||||
override val isSdkSupported: Boolean get() = false
|
||||
|
||||
@@ -4082,6 +4139,52 @@ sealed class VaultAddEditAction {
|
||||
*/
|
||||
data class BankContactPhoneTextChange(val phone: String) : BankAccountType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents actions specific to the License type.
|
||||
*/
|
||||
sealed class LicenseType : ItemType() {
|
||||
|
||||
/**
|
||||
* Fired when the first name text input is changed.
|
||||
*/
|
||||
data class FirstNameTextChange(val firstName: String) : LicenseType()
|
||||
|
||||
/**
|
||||
* Fired when the middle name text input is changed.
|
||||
*/
|
||||
data class MiddleNameTextChange(val middleName: String) : LicenseType()
|
||||
|
||||
/**
|
||||
* Fired when the last name text input is changed.
|
||||
*/
|
||||
data class LastNameTextChange(val lastName: String) : LicenseType()
|
||||
|
||||
/**
|
||||
* Fired when the license number text input is changed.
|
||||
*/
|
||||
data class LicenseNumberTextChange(val licenseNumber: String) : LicenseType()
|
||||
|
||||
/**
|
||||
* Fired when the issuing country text input is changed.
|
||||
*/
|
||||
data class IssuingCountryTextChange(val country: String) : LicenseType()
|
||||
|
||||
/**
|
||||
* Fired when the issuing state/province text input is changed.
|
||||
*/
|
||||
data class IssuingStateTextChange(val state: String) : LicenseType()
|
||||
|
||||
/**
|
||||
* Fired when the issuing authority text input is changed.
|
||||
*/
|
||||
data class IssuingAuthorityTextChange(val authority: String) : LicenseType()
|
||||
|
||||
/**
|
||||
* Fired when the license class text input is changed.
|
||||
*/
|
||||
data class LicenseClassTextChange(val licenseClass: String) : LicenseType()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package com.x8bit.bitwarden.ui.vault.feature.addedit.handlers
|
||||
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditAction
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditViewModel
|
||||
|
||||
/**
|
||||
* A collection of handler functions for managing user interactions on the License portion of the
|
||||
* Add/Edit cipher screen.
|
||||
*
|
||||
* @property onFirstNameTextChange Handles changes to the first name text input.
|
||||
* @property onMiddleNameTextChange Handles changes to the middle name text input.
|
||||
* @property onLastNameTextChange Handles changes to the last name text input.
|
||||
* @property onLicenseNumberTextChange Handles changes to the license number text input.
|
||||
* @property onIssuingCountryTextChange Handles changes to the issuing country text input.
|
||||
* @property onIssuingStateTextChange Handles changes to the issuing state/province text input.
|
||||
* @property onIssuingAuthorityTextChange Handles changes to the issuing authority text input.
|
||||
* @property onLicenseClassTextChange Handles changes to the license class text input.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
data class VaultAddEditLicenseTypeHandlers(
|
||||
val onFirstNameTextChange: (String) -> Unit,
|
||||
val onMiddleNameTextChange: (String) -> Unit,
|
||||
val onLastNameTextChange: (String) -> Unit,
|
||||
val onLicenseNumberTextChange: (String) -> Unit,
|
||||
val onIssuingCountryTextChange: (String) -> Unit,
|
||||
val onIssuingStateTextChange: (String) -> Unit,
|
||||
val onIssuingAuthorityTextChange: (String) -> Unit,
|
||||
val onLicenseClassTextChange: (String) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* Creates an instance of [VaultAddEditLicenseTypeHandlers] by binding actions to
|
||||
* the provided [VaultAddEditViewModel].
|
||||
*/
|
||||
@Suppress("LongMethod")
|
||||
fun create(
|
||||
viewModel: VaultAddEditViewModel,
|
||||
): VaultAddEditLicenseTypeHandlers =
|
||||
VaultAddEditLicenseTypeHandlers(
|
||||
onFirstNameTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.FirstNameTextChange(
|
||||
firstName = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onMiddleNameTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.MiddleNameTextChange(
|
||||
middleName = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onLastNameTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.LastNameTextChange(
|
||||
lastName = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onLicenseNumberTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.LicenseNumberTextChange(
|
||||
licenseNumber = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onIssuingCountryTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.IssuingCountryTextChange(
|
||||
country = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onIssuingStateTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.IssuingStateTextChange(
|
||||
state = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onIssuingAuthorityTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.IssuingAuthorityTextChange(
|
||||
authority = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
onLicenseClassTextChange = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.LicenseClassTextChange(
|
||||
licenseClass = it,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1692,7 +1692,7 @@ data class VaultItemState(
|
||||
VaultItemCipherType.SECURE_NOTE -> BitwardenString.view_note.asText()
|
||||
VaultItemCipherType.SSH_KEY -> BitwardenString.view_ssh_key.asText()
|
||||
VaultItemCipherType.BANK_ACCOUNT -> BitwardenString.view_bank_account.asText()
|
||||
VaultItemCipherType.DRIVERS_LICENSE -> BitwardenString.view_drivers_license.asText()
|
||||
VaultItemCipherType.DRIVERS_LICENSE -> BitwardenString.view_license.asText()
|
||||
VaultItemCipherType.PASSPORT -> BitwardenString.view_passport.asText()
|
||||
}
|
||||
|
||||
|
||||
+148
@@ -2779,6 +2779,138 @@ class VaultAddEditScreenTest : BitwardenComposeTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in ItemType_License changing first name should trigger FirstNameTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_LICENSE
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "First name")
|
||||
.performTextInput(text = "Missy")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.FirstNameTextChange(
|
||||
firstName = "Missy",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in ItemType_License changing middle name should trigger MiddleNameTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_LICENSE
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Middle name")
|
||||
.performTextInput(text = "Anne")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.MiddleNameTextChange(
|
||||
middleName = "Anne",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in ItemType_License changing last name should trigger LastNameTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_LICENSE
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Last name")
|
||||
.performTextInput(text = "Katner")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.LastNameTextChange(
|
||||
lastName = "Katner",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in ItemType_License changing the license number text field should trigger LicenseNumberTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_LICENSE
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "License number")
|
||||
.performTextInput(text = "K123-456-789")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.LicenseNumberTextChange(
|
||||
licenseNumber = "K123-456-789",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in ItemType_License changing the issuing country text field should trigger IssuingCountryTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_LICENSE
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Issuing country")
|
||||
.performTextInput(text = "USA")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.IssuingCountryTextChange(
|
||||
country = "USA",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in ItemType_License changing the issuing state text field should trigger IssuingStateTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_LICENSE
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Issuing state / province")
|
||||
.performTextInput(text = "Wisconsin")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.IssuingStateTextChange(
|
||||
state = "Wisconsin",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in ItemType_License changing the issuing authority text field should trigger IssuingAuthorityTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_LICENSE
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "Issuing authority")
|
||||
.performTextInput(text = "DMV")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.IssuingAuthorityTextChange(
|
||||
authority = "DMV",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in ItemType_License changing license class should trigger LicenseClassTextChange`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_LICENSE
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "License class")
|
||||
.performTextInput(text = "Class D")
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.LicenseClassTextChange(
|
||||
licenseClass = "Class D",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `clicking Add field button should allow creation of Linked type`() {
|
||||
mutableStateFlow.value = DEFAULT_STATE_LOGIN
|
||||
@@ -4889,6 +5021,22 @@ class VaultAddEditScreenTest : BitwardenComposeTest() {
|
||||
isCardScannerEnabled = false,
|
||||
)
|
||||
|
||||
private val DEFAULT_STATE_LICENSE = VaultAddEditState(
|
||||
vaultAddEditType = VaultAddEditType.AddItem,
|
||||
cipherType = VaultItemCipherType.DRIVERS_LICENSE,
|
||||
viewState = VaultAddEditState.ViewState.Content(
|
||||
common = VaultAddEditState.ViewState.Content.Common(),
|
||||
type = VaultAddEditState.ViewState.Content.ItemType.License(),
|
||||
isIndividualVaultDisabled = false,
|
||||
),
|
||||
dialog = null,
|
||||
bottomSheetState = null,
|
||||
shouldShowCoachMarkTour = false,
|
||||
defaultUriMatchType = UriMatchTypeModel.EXACT,
|
||||
hasPremium = false,
|
||||
isCardScannerEnabled = false,
|
||||
)
|
||||
|
||||
private val DEFAULT_STATE_SECURE_NOTES_CUSTOM_FIELDS = VaultAddEditState(
|
||||
viewState = VaultAddEditState.ViewState.Content(
|
||||
common = VaultAddEditState.ViewState.Content.Common(
|
||||
|
||||
+159
-8
@@ -2408,9 +2408,8 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in add mode, SaveClick with a Drivers License item should emit ShowSnackbar without saving`() =
|
||||
fun `in add mode, SaveClick with a License item should emit ShowSnackbar without saving`() =
|
||||
runTest {
|
||||
mutableVaultDataFlow.value = DataState.Loaded(createVaultData())
|
||||
val licenseState = createVaultAddItemState(
|
||||
@@ -2522,12 +2521,11 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
assertTrue(itemType.vaultLinkedFieldTypes.isEmpty())
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `ItemType DriversLicense should expose DRIVERS_LICENSE itemTypeOption and not be SDK supported`() {
|
||||
fun `ItemType License should expose DRIVERS_LICENSE itemTypeOption and not be SDK supported`() {
|
||||
val itemType = VaultAddEditState.ViewState.Content.ItemType.License()
|
||||
assertEquals(
|
||||
VaultAddEditState.ItemTypeOption.DRIVERS_LICENSE,
|
||||
VaultAddEditState.ItemTypeOption.LICENSE,
|
||||
itemType.itemTypeOption,
|
||||
)
|
||||
assertFalse(itemType.isSdkSupported)
|
||||
@@ -2554,7 +2552,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
baseAddState.copy(cipherType = VaultItemCipherType.BANK_ACCOUNT).screenDisplayName,
|
||||
)
|
||||
assertEquals(
|
||||
BitwardenString.new_drivers_license.asText(),
|
||||
BitwardenString.new_license.asText(),
|
||||
baseAddState.copy(cipherType = VaultItemCipherType.DRIVERS_LICENSE).screenDisplayName,
|
||||
)
|
||||
assertEquals(
|
||||
@@ -2574,7 +2572,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
baseEditState.copy(cipherType = VaultItemCipherType.BANK_ACCOUNT).screenDisplayName,
|
||||
)
|
||||
assertEquals(
|
||||
BitwardenString.edit_drivers_license.asText(),
|
||||
BitwardenString.edit_license.asText(),
|
||||
baseEditState.copy(cipherType = VaultItemCipherType.DRIVERS_LICENSE).screenDisplayName,
|
||||
)
|
||||
assertEquals(
|
||||
@@ -2594,7 +2592,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
baseCloneState.copy(cipherType = VaultItemCipherType.BANK_ACCOUNT).screenDisplayName,
|
||||
)
|
||||
assertEquals(
|
||||
BitwardenString.new_drivers_license.asText(),
|
||||
BitwardenString.new_license.asText(),
|
||||
baseCloneState.copy(cipherType = VaultItemCipherType.DRIVERS_LICENSE).screenDisplayName,
|
||||
)
|
||||
assertEquals(
|
||||
@@ -4189,6 +4187,159 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class VaultAddEditLicenseTypeItemActions {
|
||||
private lateinit var viewModel: VaultAddEditViewModel
|
||||
private lateinit var vaultAddItemInitialState: VaultAddEditState
|
||||
private lateinit var licenseInitialSavedStateHandle: SavedStateHandle
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
mutableVaultDataFlow.value = DataState.Loaded(
|
||||
createVaultData(cipherListView = createMockCipherListView(1)),
|
||||
)
|
||||
vaultAddItemInitialState = createVaultAddItemState(
|
||||
vaultItemCipherType = VaultItemCipherType.DRIVERS_LICENSE,
|
||||
typeContentViewState =
|
||||
VaultAddEditState.ViewState.Content.ItemType.License(),
|
||||
)
|
||||
licenseInitialSavedStateHandle = createSavedStateHandleWithState(
|
||||
state = vaultAddItemInitialState,
|
||||
vaultAddEditType = VaultAddEditType.AddItem,
|
||||
vaultItemCipherType = VaultItemCipherType.DRIVERS_LICENSE,
|
||||
)
|
||||
viewModel = createAddVaultItemViewModel(
|
||||
savedStateHandle = licenseInitialSavedStateHandle,
|
||||
)
|
||||
}
|
||||
|
||||
private fun expectedLicense(
|
||||
block: VaultAddEditState.ViewState.Content.ItemType.License.() ->
|
||||
VaultAddEditState.ViewState.Content.ItemType.License,
|
||||
): VaultAddEditState =
|
||||
createVaultAddItemState(
|
||||
vaultItemCipherType = VaultItemCipherType.DRIVERS_LICENSE,
|
||||
typeContentViewState = VaultAddEditState
|
||||
.ViewState
|
||||
.Content
|
||||
.ItemType
|
||||
.License()
|
||||
.block(),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `FirstNameTextChange should update first name`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.FirstNameTextChange(
|
||||
firstName = "Missy",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedLicense { copy(firstName = "Missy") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `MiddleNameTextChange should update middle name`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.MiddleNameTextChange(
|
||||
middleName = "Anne",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedLicense { copy(middleName = "Anne") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `LastNameTextChange should update last name`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.LastNameTextChange(
|
||||
lastName = "Katner",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedLicense { copy(lastName = "Katner") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `LicenseNumberTextChange should update license number`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.LicenseNumberTextChange(
|
||||
licenseNumber = "K123-456-789",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedLicense { copy(licenseNumber = "K123-456-789") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `IssuingCountryTextChange should update issuing country`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.IssuingCountryTextChange(
|
||||
country = "USA",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedLicense { copy(issuingCountry = "USA") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `IssuingStateTextChange should update issuing state`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.IssuingStateTextChange(
|
||||
state = "Wisconsin",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedLicense { copy(issuingState = "Wisconsin") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `IssuingAuthorityTextChange should update issuing authority`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.IssuingAuthorityTextChange(
|
||||
authority = "DMV",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedLicense { copy(issuingAuthority = "DMV") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `LicenseClassTextChange should update license class`() = runTest {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LicenseType.LicenseClassTextChange(
|
||||
licenseClass = "Class D",
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedLicense { copy(licenseClass = "Class D") },
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NumberVisibilityChange should log an event when in edit mode and password is visible`() =
|
||||
runTest {
|
||||
|
||||
+1
-1
@@ -3831,7 +3831,7 @@ class VaultViewModelTest : BaseViewModelTest() {
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `SelectAddItemType action should not exclude bank account, drivers license, or passport when NewItemTypes flag is enabled`() {
|
||||
fun `SelectAddItemType action should not exclude bank account, license, or passport when NewItemTypes flag is enabled`() {
|
||||
mutableNewItemTypesFlagFlow.value = true
|
||||
val viewModel = createViewModel()
|
||||
|
||||
|
||||
@@ -1306,19 +1306,18 @@ Do you want to switch to this account?</string>
|
||||
<string name="subscription_error">Subscription error</string>
|
||||
<string name="trouble_loading_subscription">We couldn’t load your subscription details. Please try again.</string>
|
||||
<string name="view_bank_account">View bank account</string>
|
||||
<string name="view_drivers_license">View license</string>
|
||||
<string name="view_license">View license</string>
|
||||
<string name="view_passport">View passport</string>
|
||||
<string name="new_bank_account">New bank account</string>
|
||||
<string name="new_drivers_license">New license</string>
|
||||
<string name="new_license">New license</string>
|
||||
<string name="new_passport">New passport</string>
|
||||
<string name="edit_bank_account">Edit bank account</string>
|
||||
<string name="edit_drivers_license">Edit license</string>
|
||||
<string name="edit_license">Edit license</string>
|
||||
<string name="edit_passport">Edit passport</string>
|
||||
<string name="type_bank_account">Bank account</string>
|
||||
<string name="type_license">License</string>
|
||||
<string name="type_passport">Passport</string>
|
||||
<string name="bank_accounts">Bank accounts</string>
|
||||
<string name="drivers_licenses">Driver’s licenses</string>
|
||||
<string name="passports">Passports</string>
|
||||
<string name="bank_name">Bank name</string>
|
||||
<string name="name_on_account">Name on account</string>
|
||||
|
||||
Reference in New Issue
Block a user