mirror of
https://github.com/bitwarden/android.git
synced 2025-12-12 00:08:00 -06:00
PM-18275: Add totp tooltip on view item screen (#4732)
This commit is contained in:
parent
22931bbd38
commit
9f19a99eb9
@ -80,6 +80,7 @@ import kotlinx.collections.immutable.toImmutableList
|
||||
* @param value current next on the text field.
|
||||
* @param modifier modifier for the composable.
|
||||
* @param onValueChange callback that is triggered when the input of the text field changes.
|
||||
* @param tooltip the optional tooltip to be displayed in the label.
|
||||
* @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.
|
||||
@ -109,6 +110,7 @@ fun BitwardenTextField(
|
||||
onValueChange: (String) -> Unit,
|
||||
cardStyle: CardStyle,
|
||||
modifier: Modifier = Modifier,
|
||||
tooltip: TooltipData? = null,
|
||||
placeholder: String? = null,
|
||||
leadingIconResource: IconResource? = null,
|
||||
supportingText: String? = null,
|
||||
@ -133,6 +135,7 @@ fun BitwardenTextField(
|
||||
label = label,
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
tooltip = tooltip,
|
||||
placeholder = placeholder,
|
||||
leadingIconResource = leadingIconResource,
|
||||
supportingContent = supportingText?.let {
|
||||
@ -171,6 +174,7 @@ fun BitwardenTextField(
|
||||
* @param label label for the text field.
|
||||
* @param value current next on the text field.
|
||||
* @param modifier modifier for the composable.
|
||||
* @param tooltip the optional tooltip to be displayed in the label.
|
||||
* @param onValueChange callback that is triggered when the input of the text field changes.
|
||||
* @param supportingContent An optional supporting content composable that will appear below the
|
||||
* text input.
|
||||
|
||||
@ -25,6 +25,7 @@ import com.x8bit.bitwarden.ui.platform.components.field.BitwardenTextField
|
||||
import com.x8bit.bitwarden.ui.platform.components.header.BitwardenListHeaderText
|
||||
import com.x8bit.bitwarden.ui.platform.components.indicator.BitwardenCircularCountdownIndicator
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.CardStyle
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.TooltipData
|
||||
import com.x8bit.bitwarden.ui.platform.components.text.BitwardenClickableText
|
||||
import com.x8bit.bitwarden.ui.platform.components.text.BitwardenHyperTextLink
|
||||
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
@ -141,6 +142,8 @@ fun VaultItemLoginContent(
|
||||
totpCodeItemData = totpCodeItemData,
|
||||
enabled = loginItemState.canViewTotpCode,
|
||||
onCopyTotpClick = vaultLoginItemTypeHandlers.onCopyTotpCodeClick,
|
||||
onAuthenticatorHelpToolTipClick = vaultLoginItemTypeHandlers
|
||||
.onAuthenticatorHelpToolTipClick,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
@ -399,6 +402,7 @@ private fun TotpField(
|
||||
totpCodeItemData: TotpCodeItemData,
|
||||
enabled: Boolean,
|
||||
onCopyTotpClick: () -> Unit,
|
||||
onAuthenticatorHelpToolTipClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (enabled) {
|
||||
@ -411,6 +415,10 @@ private fun TotpField(
|
||||
textStyle = BitwardenTheme.typography.sensitiveInfoSmall,
|
||||
readOnly = true,
|
||||
singleLine = true,
|
||||
tooltip = TooltipData(
|
||||
onClick = onAuthenticatorHelpToolTipClick,
|
||||
contentDescription = stringResource(id = R.string.authenticator_key_help),
|
||||
),
|
||||
actions = {
|
||||
BitwardenCircularCountdownIndicator(
|
||||
timeLeftSeconds = totpCodeItemData.timeLeftSeconds,
|
||||
@ -431,6 +439,10 @@ private fun TotpField(
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = R.string.authenticator_key),
|
||||
value = "",
|
||||
tooltip = TooltipData(
|
||||
onClick = onAuthenticatorHelpToolTipClick,
|
||||
contentDescription = stringResource(id = R.string.authenticator_key_help),
|
||||
),
|
||||
supportingText = stringResource(id = R.string.premium_subscription_required),
|
||||
enabled = false,
|
||||
singleLine = false,
|
||||
|
||||
@ -530,6 +530,10 @@ class VaultItemViewModel @Inject constructor(
|
||||
|
||||
private fun handleLoginTypeActions(action: VaultItemAction.ItemType.Login) {
|
||||
when (action) {
|
||||
is VaultItemAction.ItemType.Login.AuthenticatorHelpToolTipClick -> {
|
||||
handleAuthenticatorHelpToolTipClick()
|
||||
}
|
||||
|
||||
is VaultItemAction.ItemType.Login.CheckForBreachClick -> {
|
||||
handleCheckForBreachClick()
|
||||
}
|
||||
@ -564,6 +568,14 @@ class VaultItemViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleAuthenticatorHelpToolTipClick() {
|
||||
sendEvent(
|
||||
event = VaultItemEvent.NavigateToUri(
|
||||
uri = "https://bitwarden.com/help/integrated-authenticator",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleCheckForBreachClick() {
|
||||
onLoginContent { _, login ->
|
||||
val password = requireNotNull(login.passwordData?.password)
|
||||
@ -1991,6 +2003,11 @@ sealed class VaultItemAction {
|
||||
* Represents actions specific to the Login type.
|
||||
*/
|
||||
sealed class Login : ItemType() {
|
||||
/**
|
||||
* The user has clicked the call to action on the authenticator help tooltip.
|
||||
*/
|
||||
data object AuthenticatorHelpToolTipClick : Login()
|
||||
|
||||
/**
|
||||
* The user has clicked the check for breach button.
|
||||
*/
|
||||
|
||||
@ -12,6 +12,7 @@ data class VaultLoginItemTypeHandlers(
|
||||
val onCheckForBreachClick: () -> Unit,
|
||||
val onCopyPasswordClick: () -> Unit,
|
||||
val onCopyTotpCodeClick: () -> Unit,
|
||||
val onAuthenticatorHelpToolTipClick: () -> Unit,
|
||||
val onCopyUriClick: (String) -> Unit,
|
||||
val onCopyUsernameClick: () -> Unit,
|
||||
val onLaunchUriClick: (String) -> Unit,
|
||||
@ -37,6 +38,11 @@ data class VaultLoginItemTypeHandlers(
|
||||
onCopyTotpCodeClick = {
|
||||
viewModel.trySendAction(VaultItemAction.ItemType.Login.CopyTotpClick)
|
||||
},
|
||||
onAuthenticatorHelpToolTipClick = {
|
||||
viewModel.trySendAction(
|
||||
VaultItemAction.ItemType.Login.AuthenticatorHelpToolTipClick,
|
||||
)
|
||||
},
|
||||
onCopyUriClick = {
|
||||
viewModel.trySendAction(VaultItemAction.ItemType.Login.CopyUriClick(it))
|
||||
},
|
||||
|
||||
@ -1727,6 +1727,21 @@ class VaultItemScreenTest : BaseComposeTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in login state, on totp help tooltip click should send AuthenticatorHelpToolTipClick`() {
|
||||
mutableStateFlow.update { currentState ->
|
||||
currentState.copy(viewState = DEFAULT_LOGIN_VIEW_STATE)
|
||||
}
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithContentDescriptionAfterScroll("Authenticator key help")
|
||||
.performClick()
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(VaultItemAction.ItemType.Login.AuthenticatorHelpToolTipClick)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `in login state, launch uri button should be displayed according to state`() {
|
||||
val uriData = VaultItemState.ViewState.Content.ItemType.Login.UriData(
|
||||
|
||||
@ -2001,6 +2001,21 @@ class VaultItemViewModelTest : BaseViewModelTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `on AuthenticatorHelpToolTipClick should emit NavigateToUri`() = runTest {
|
||||
viewModel.eventFlow.test {
|
||||
viewModel.trySendAction(
|
||||
action = VaultItemAction.ItemType.Login.AuthenticatorHelpToolTipClick,
|
||||
)
|
||||
assertEquals(
|
||||
VaultItemEvent.NavigateToUri(
|
||||
"https://bitwarden.com/help/integrated-authenticator",
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `on PasswordHistoryClick should show password dialog when re-prompt is required`() =
|
||||
runTest {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user