mirror of
https://github.com/bitwarden/android.git
synced 2025-03-15 10:48:47 +03:00
BIT-1103 Adding the ability to delete totp text (#562)
This commit is contained in:
parent
3c00a41d84
commit
9c023bca9e
7 changed files with 93 additions and 0 deletions
|
@ -32,6 +32,7 @@ import com.x8bit.bitwarden.ui.platform.components.model.IconResource
|
|||
* @param placeholder the optional placeholder to be displayed when the text field is in focus and
|
||||
* the [value] is empty.
|
||||
* @param leadingIconResource the optional resource for the leading icon on the text field.
|
||||
* @param trailingIconContent the content for the trailing icon in the text field.
|
||||
* @param hint optional hint text that will appear below the text input.
|
||||
* @param singleLine when `true`, this text field becomes a single line that horizontally scrolls
|
||||
* instead of wrapping onto multiple lines.
|
||||
|
@ -51,6 +52,7 @@ fun BitwardenTextField(
|
|||
modifier: Modifier = Modifier,
|
||||
placeholder: String? = null,
|
||||
leadingIconResource: IconResource? = null,
|
||||
trailingIconContent: (@Composable () -> Unit)? = null,
|
||||
hint: String? = null,
|
||||
singleLine: Boolean = true,
|
||||
readOnly: Boolean = false,
|
||||
|
@ -88,6 +90,9 @@ fun BitwardenTextField(
|
|||
)
|
||||
}
|
||||
},
|
||||
trailingIcon = trailingIconContent?.let {
|
||||
trailingIconContent
|
||||
},
|
||||
placeholder = placeholder?.let {
|
||||
{ Text(text = it) }
|
||||
},
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
|||
* @param readOnly `true` if the input should be read-only and not accept user interactions.
|
||||
* @param singleLine when `true`, this text field becomes a single line that horizontally scrolls
|
||||
* instead of wrapping onto multiple lines.
|
||||
* @param trailingIconContent the content for the trailing icon in the text field.
|
||||
* @param actions A lambda containing the set of actions (usually icons or similar) to display
|
||||
* next to the text field. This lambda extends [RowScope],
|
||||
* providing flexibility in the layout definition.
|
||||
|
@ -38,6 +39,7 @@ fun BitwardenTextFieldWithActions(
|
|||
readOnly: Boolean = false,
|
||||
singleLine: Boolean = true,
|
||||
keyboardType: KeyboardType = KeyboardType.Text,
|
||||
trailingIconContent: (@Composable () -> Unit)? = null,
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
) {
|
||||
Row(
|
||||
|
@ -53,6 +55,7 @@ fun BitwardenTextFieldWithActions(
|
|||
singleLine = singleLine,
|
||||
onValueChange = onValueChange,
|
||||
keyboardType = keyboardType,
|
||||
trailingIconContent = trailingIconContent,
|
||||
)
|
||||
BitwardenRowOfActions(actions)
|
||||
}
|
||||
|
|
|
@ -130,6 +130,16 @@ fun LazyListScope.vaultAddEditLoginItems(
|
|||
.padding(horizontal = 16.dp),
|
||||
label = stringResource(id = R.string.totp),
|
||||
value = loginState.totp,
|
||||
trailingIconContent = {
|
||||
IconButton(
|
||||
onClick = loginItemTypeHandlers.onClearTotpKeyClick,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_close),
|
||||
contentDescription = stringResource(id = R.string.delete),
|
||||
)
|
||||
}
|
||||
},
|
||||
onValueChange = {},
|
||||
readOnly = true,
|
||||
singleLine = true,
|
||||
|
|
|
@ -382,6 +382,10 @@ class VaultAddEditViewModel @Inject constructor(
|
|||
is VaultAddEditAction.ItemType.LoginType.CopyTotpKeyClick -> {
|
||||
handleLoginCopyTotpKeyText(action)
|
||||
}
|
||||
|
||||
is VaultAddEditAction.ItemType.LoginType.ClearTotpKeyClick -> {
|
||||
handleLoginClearTotpKey()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,6 +459,12 @@ class VaultAddEditViewModel @Inject constructor(
|
|||
clipboardManager.setText(text = action.totpKey)
|
||||
}
|
||||
|
||||
private fun handleLoginClearTotpKey() {
|
||||
updateLoginContent { loginType ->
|
||||
loginType.copy(totp = null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleLoginUriSettingsClick() {
|
||||
viewModelScope.launch {
|
||||
sendEvent(
|
||||
|
@ -1450,6 +1460,11 @@ sealed class VaultAddEditAction {
|
|||
*/
|
||||
data class CopyTotpKeyClick(val totpKey: String) : LoginType()
|
||||
|
||||
/**
|
||||
* Represents the action to clear the totp code.
|
||||
*/
|
||||
data object ClearTotpKeyClick : LoginType()
|
||||
|
||||
/**
|
||||
* Represents the action to open the username generator.
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,8 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditViewModel
|
|||
* @property onOpenPasswordGeneratorClick Handles the action when the password generator
|
||||
* button is clicked.
|
||||
* @property onSetupTotpClick Handles the action when the setup TOTP button is clicked.
|
||||
* @property onCopyTotpKeyClick Handles the action when the copy TOTP text button is clicked.
|
||||
* @property onClearTotpKeyClick Handles the action when the clear TOTP text button is clicked.
|
||||
* @property onUriSettingsClick Handles the action when the URI settings button is clicked.
|
||||
* @property onAddNewUriClick Handles the action when the add new URI button is clicked.
|
||||
*/
|
||||
|
@ -31,6 +33,7 @@ data class VaultAddEditLoginTypeHandlers(
|
|||
val onOpenPasswordGeneratorClick: () -> Unit,
|
||||
val onSetupTotpClick: (Boolean) -> Unit,
|
||||
val onCopyTotpKeyClick: (String) -> Unit,
|
||||
val onClearTotpKeyClick: () -> Unit,
|
||||
val onUriSettingsClick: () -> Unit,
|
||||
val onAddNewUriClick: () -> Unit,
|
||||
) {
|
||||
|
@ -94,6 +97,11 @@ data class VaultAddEditLoginTypeHandlers(
|
|||
),
|
||||
)
|
||||
},
|
||||
onClearTotpKeyClick = {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LoginType.ClearTotpKeyClick,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
|
|||
import com.x8bit.bitwarden.ui.platform.base.util.FakePermissionManager
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
import com.x8bit.bitwarden.ui.util.isProgressBar
|
||||
import com.x8bit.bitwarden.ui.util.onAllNodesWithContentDescriptionAfterScroll
|
||||
import com.x8bit.bitwarden.ui.util.onAllNodesWithTextAfterScroll
|
||||
import com.x8bit.bitwarden.ui.util.onNodeWithContentDescriptionAfterScroll
|
||||
import com.x8bit.bitwarden.ui.util.onNodeWithTextAfterScroll
|
||||
|
@ -457,6 +458,25 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
.assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in ItemType_Login state the totp text field click on trailing icon should call ClearTotpKeyClick`() {
|
||||
mutableStateFlow.update { currentState ->
|
||||
updateLoginType(currentState) { copy(totp = "TestCode") }
|
||||
}
|
||||
|
||||
composeTestRule
|
||||
.onAllNodesWithContentDescriptionAfterScroll("Delete")
|
||||
.onFirst()
|
||||
.performClick()
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LoginType.ClearTotpKeyClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in ItemType_Login state clicking the copy totp code button should trigger CopyTotpKeyClick`() {
|
||||
|
|
|
@ -674,6 +674,38 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ClearTotpKeyClick call should clear the totp code`() {
|
||||
val viewModel = createAddVaultItemViewModel(
|
||||
savedStateHandle = createSavedStateHandleWithState(
|
||||
state = createVaultAddItemState(
|
||||
typeContentViewState = createLoginTypeContentViewState(
|
||||
totpCode = "testCode",
|
||||
),
|
||||
),
|
||||
vaultAddEditType = VaultAddEditType.EditItem(DEFAULT_EDIT_ITEM_ID),
|
||||
),
|
||||
)
|
||||
|
||||
val expectedState = loginInitialState.copy(
|
||||
viewState = VaultAddEditState.ViewState.Content(
|
||||
common = createCommonContentViewState(),
|
||||
type = createLoginTypeContentViewState(
|
||||
totpCode = null,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
viewModel.actionChannel.trySend(
|
||||
VaultAddEditAction.ItemType.LoginType.ClearTotpKeyClick,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expectedState,
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `TotpCodeReceive should update totp code in state`() = runTest {
|
||||
val viewModel = createAddVaultItemViewModel()
|
||||
|
|
Loading…
Add table
Reference in a new issue