PM-12773 show autofill card when user skipped this step in onboarding (#4021)

This commit is contained in:
Dave Severns 2024-10-04 14:21:40 -04:00 committed by GitHub
parent a5cf4f49d7
commit 83652c9699
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 237 additions and 16 deletions

View file

@ -1,6 +1,8 @@
package com.x8bit.bitwarden.ui.platform.components.card package com.x8bit.bitwarden.ui.platform.components.card
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -89,6 +91,12 @@ fun BitwardenActionCard(
} }
} }
/**
* A default exit animation for [BitwardenActionCard] when using an animation wrapper like
* [AnimatedVisibility].
*/
fun actionCardExitAnimation() = fadeOut() + shrinkVertically(shrinkTowards = Alignment.Top)
@Preview @Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable @Composable

View file

@ -2,8 +2,6 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity
import android.widget.Toast import android.widget.Toast
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -23,7 +21,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@ -44,6 +41,7 @@ import com.x8bit.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
import com.x8bit.bitwarden.ui.platform.components.badge.NotificationBadge import com.x8bit.bitwarden.ui.platform.components.badge.NotificationBadge
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenTextButton import com.x8bit.bitwarden.ui.platform.components.button.BitwardenTextButton
import com.x8bit.bitwarden.ui.platform.components.card.BitwardenActionCard import com.x8bit.bitwarden.ui.platform.components.card.BitwardenActionCard
import com.x8bit.bitwarden.ui.platform.components.card.actionCardExitAnimation
import com.x8bit.bitwarden.ui.platform.components.dialog.BasicDialogState import com.x8bit.bitwarden.ui.platform.components.dialog.BasicDialogState
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenLoadingDialog import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenLoadingDialog
@ -183,7 +181,7 @@ fun AccountSecurityScreen(
AnimatedVisibility( AnimatedVisibility(
visible = state.shouldShowUnlockActionCard, visible = state.shouldShowUnlockActionCard,
label = "UnlockActionCard", label = "UnlockActionCard",
exit = fadeOut() + shrinkVertically(shrinkTowards = Alignment.Top), exit = actionCardExitAnimation(),
) { ) {
BitwardenActionCard( BitwardenActionCard(
cardTitle = stringResource(id = R.string.set_up_unlock), cardTitle = stringResource(id = R.string.set_up_unlock),

View file

@ -1,6 +1,7 @@
package com.x8bit.bitwarden.ui.platform.feature.settings.autofill package com.x8bit.bitwarden.ui.platform.feature.settings.autofill
import android.widget.Toast import android.widget.Toast
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -31,7 +32,11 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.base.util.standardHorizontalMargin
import com.x8bit.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
import com.x8bit.bitwarden.ui.platform.components.badge.NotificationBadge
import com.x8bit.bitwarden.ui.platform.components.card.BitwardenActionCard
import com.x8bit.bitwarden.ui.platform.components.card.actionCardExitAnimation
import com.x8bit.bitwarden.ui.platform.components.dialog.BasicDialogState import com.x8bit.bitwarden.ui.platform.components.dialog.BasicDialogState
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenSelectionDialog import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenSelectionDialog
@ -125,6 +130,32 @@ fun AutoFillScreen(
.fillMaxSize() .fillMaxSize()
.verticalScroll(rememberScrollState()), .verticalScroll(rememberScrollState()),
) { ) {
AnimatedVisibility(
visible = state.showAutofillActionCard,
label = "AutofillActionCard",
exit = actionCardExitAnimation(),
) {
BitwardenActionCard(
cardTitle = stringResource(R.string.turn_on_autofill),
actionText = stringResource(R.string.get_started),
onActionClick = remember(viewModel) {
{
viewModel.trySendAction(AutoFillAction.AutoFillActionCardCtaClick)
}
},
onDismissClick = remember(viewModel) {
{
viewModel.trySendAction(AutoFillAction.DismissShowAutofillActionCard)
}
},
leadingContent = {
NotificationBadge(notificationCount = 1)
},
modifier = Modifier
.standardHorizontalMargin()
.padding(top = 12.dp, bottom = 16.dp),
)
}
BitwardenListHeaderText( BitwardenListHeaderText(
label = stringResource(id = R.string.autofill), label = stringResource(id = R.string.autofill),
modifier = Modifier modifier = Modifier

View file

@ -4,6 +4,7 @@ import android.os.Build
import android.os.Parcelable import android.os.Parcelable
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow
@ -25,22 +26,30 @@ private const val KEY_STATE = "state"
@Suppress("TooManyFunctions") @Suppress("TooManyFunctions")
@HiltViewModel @HiltViewModel
class AutoFillViewModel @Inject constructor( class AutoFillViewModel @Inject constructor(
authRepository: AuthRepository,
private val savedStateHandle: SavedStateHandle, private val savedStateHandle: SavedStateHandle,
private val settingsRepository: SettingsRepository, private val settingsRepository: SettingsRepository,
) : BaseViewModel<AutoFillState, AutoFillEvent, AutoFillAction>( ) : BaseViewModel<AutoFillState, AutoFillEvent, AutoFillAction>(
initialState = savedStateHandle[KEY_STATE] initialState = savedStateHandle[KEY_STATE]
?: AutoFillState( ?: run {
isAskToAddLoginEnabled = !settingsRepository.isAutofillSavePromptDisabled, val userId = requireNotNull(authRepository.userStateFlow.value).activeUserId
isAccessibilityAutofillEnabled = settingsRepository AutoFillState(
.isAccessibilityEnabledStateFlow isAskToAddLoginEnabled = !settingsRepository.isAutofillSavePromptDisabled,
.value, isAccessibilityAutofillEnabled = settingsRepository
isAutoFillServicesEnabled = settingsRepository.isAutofillEnabledStateFlow.value, .isAccessibilityEnabledStateFlow
isCopyTotpAutomaticallyEnabled = !settingsRepository.isAutoCopyTotpDisabled, .value,
isUseInlineAutoFillEnabled = settingsRepository.isInlineAutofillEnabled, isAutoFillServicesEnabled = settingsRepository.isAutofillEnabledStateFlow.value,
showInlineAutofillOption = !isBuildVersionBelow(Build.VERSION_CODES.R), isCopyTotpAutomaticallyEnabled = !settingsRepository.isAutoCopyTotpDisabled,
showPasskeyManagementRow = !isBuildVersionBelow(Build.VERSION_CODES.UPSIDE_DOWN_CAKE), isUseInlineAutoFillEnabled = settingsRepository.isInlineAutofillEnabled,
defaultUriMatchType = settingsRepository.defaultUriMatchType, showInlineAutofillOption = !isBuildVersionBelow(Build.VERSION_CODES.R),
), showPasskeyManagementRow = !isBuildVersionBelow(
Build.VERSION_CODES.UPSIDE_DOWN_CAKE,
),
defaultUriMatchType = settingsRepository.defaultUriMatchType,
showAutofillActionCard = false,
activeUserId = userId,
)
},
) { ) {
init { init {
@ -64,6 +73,12 @@ class AutoFillViewModel @Inject constructor(
} }
.onEach(::sendAction) .onEach(::sendAction)
.launchIn(viewModelScope) .launchIn(viewModelScope)
settingsRepository
.getShowAutofillBadgeFlow(userId = state.activeUserId)
.map { AutoFillAction.Internal.UpdateShowAutofillActionCard(it) }
.onEach(::sendAction)
.launchIn(viewModelScope)
} }
override fun handleAction(action: AutoFillAction) = when (action) { override fun handleAction(action: AutoFillAction) = when (action) {
@ -77,6 +92,8 @@ class AutoFillViewModel @Inject constructor(
is AutoFillAction.UseInlineAutofillClick -> handleUseInlineAutofillClick(action) is AutoFillAction.UseInlineAutofillClick -> handleUseInlineAutofillClick(action)
AutoFillAction.PasskeyManagementClick -> handlePasskeyManagementClick() AutoFillAction.PasskeyManagementClick -> handlePasskeyManagementClick()
is AutoFillAction.Internal -> handleInternalAction(action) is AutoFillAction.Internal -> handleInternalAction(action)
AutoFillAction.AutoFillActionCardCtaClick -> handleAutoFillActionCardCtClick()
AutoFillAction.DismissShowAutofillActionCard -> handleDismissShowAutofillActionCard()
} }
private fun handleInternalAction(action: AutoFillAction.Internal) { private fun handleInternalAction(action: AutoFillAction.Internal) {
@ -88,9 +105,28 @@ class AutoFillViewModel @Inject constructor(
is AutoFillAction.Internal.AutofillEnabledUpdateReceive -> { is AutoFillAction.Internal.AutofillEnabledUpdateReceive -> {
handleAutofillEnabledUpdateReceive(action) handleAutofillEnabledUpdateReceive(action)
} }
is AutoFillAction.Internal.UpdateShowAutofillActionCard -> {
handleUpdateShowAutofillActionCard(action)
}
} }
} }
private fun handleDismissShowAutofillActionCard() {
dismissShowAutofillActionCard()
}
private fun handleAutoFillActionCardCtClick() {
dismissShowAutofillActionCard()
// TODO PM-13068 navigate to auto fill setup screen
}
private fun handleUpdateShowAutofillActionCard(
action: AutoFillAction.Internal.UpdateShowAutofillActionCard,
) {
mutableStateFlow.update { it.copy(showAutofillActionCard = action.showAutofillActionCard) }
}
private fun handleAskToAddLoginClick(action: AutoFillAction.AskToAddLoginClick) { private fun handleAskToAddLoginClick(action: AutoFillAction.AskToAddLoginClick) {
settingsRepository.isAutofillSavePromptDisabled = !action.isEnabled settingsRepository.isAutofillSavePromptDisabled = !action.isEnabled
mutableStateFlow.update { it.copy(isAskToAddLoginEnabled = action.isEnabled) } mutableStateFlow.update { it.copy(isAskToAddLoginEnabled = action.isEnabled) }
@ -102,6 +138,7 @@ class AutoFillViewModel @Inject constructor(
} else { } else {
settingsRepository.disableAutofill() settingsRepository.disableAutofill()
} }
dismissShowAutofillActionCard()
} }
private fun handleBackClick() { private fun handleBackClick() {
@ -154,6 +191,14 @@ class AutoFillViewModel @Inject constructor(
private fun handleBlockAutoFillClick() { private fun handleBlockAutoFillClick() {
sendEvent(AutoFillEvent.NavigateToBlockAutoFill) sendEvent(AutoFillEvent.NavigateToBlockAutoFill)
} }
private fun dismissShowAutofillActionCard() {
if (!state.showAutofillActionCard) return
settingsRepository.storeShowAutoFillSettingBadge(
userId = state.activeUserId,
showBadge = false,
)
}
} }
/** /**
@ -169,6 +214,8 @@ data class AutoFillState(
val showInlineAutofillOption: Boolean, val showInlineAutofillOption: Boolean,
val showPasskeyManagementRow: Boolean, val showPasskeyManagementRow: Boolean,
val defaultUriMatchType: UriMatchType, val defaultUriMatchType: UriMatchType,
val showAutofillActionCard: Boolean,
val activeUserId: String,
) : Parcelable { ) : Parcelable {
/** /**
@ -275,6 +322,16 @@ sealed class AutoFillAction {
*/ */
data object PasskeyManagementClick : AutoFillAction() data object PasskeyManagementClick : AutoFillAction()
/**
* User has clicked the "X" to dismiss the autofill action card.
*/
data object DismissShowAutofillActionCard : AutoFillAction()
/**
* User has clicked the CTA on the autofill action card.
*/
data object AutoFillActionCardCtaClick : AutoFillAction()
/** /**
* Internal actions. * Internal actions.
*/ */
@ -292,5 +349,10 @@ sealed class AutoFillAction {
data class AutofillEnabledUpdateReceive( data class AutofillEnabledUpdateReceive(
val isAutofillEnabled: Boolean, val isAutofillEnabled: Boolean,
) : Internal() ) : Internal()
/**
* An update for changes in the [showAutofillActionCard] value from the settings repository.
*/
data class UpdateShowAutofillActionCard(val showAutofillActionCard: Boolean) : Internal()
} }
} }

View file

@ -462,6 +462,42 @@ class AutoFillScreenTest : BaseComposeTest() {
mutableEventFlow.tryEmit(AutoFillEvent.NavigateToBlockAutoFill) mutableEventFlow.tryEmit(AutoFillEvent.NavigateToBlockAutoFill)
assertTrue(onNavigateToBlockAutoFillScreenCalled) assertTrue(onNavigateToBlockAutoFillScreenCalled)
} }
@Test
fun `autofill action card should show when state is true and hide when false`() {
composeTestRule
.onNodeWithText("Get started")
.assertDoesNotExist()
mutableStateFlow.update { DEFAULT_STATE.copy(showAutofillActionCard = true) }
composeTestRule
.onNodeWithText("Get started")
.assertIsDisplayed()
mutableStateFlow.update { DEFAULT_STATE.copy(showAutofillActionCard = false) }
composeTestRule
.onNodeWithText("Get started")
.assertDoesNotExist()
}
@Test
fun `when autofill card is visible clicking the cta button should send correct action`() {
mutableStateFlow.update { DEFAULT_STATE.copy(showAutofillActionCard = true) }
composeTestRule
.onNodeWithText("Get started")
.performScrollTo()
.performClick()
verify { viewModel.trySendAction(AutoFillAction.AutoFillActionCardCtaClick) }
}
@Test
fun `when autofill action card is visible clicking dismissing should send correct action`() {
mutableStateFlow.update { DEFAULT_STATE.copy(showAutofillActionCard = true) }
composeTestRule
.onNodeWithContentDescription("Close")
.performScrollTo()
.performClick()
verify { viewModel.trySendAction(AutoFillAction.DismissShowAutofillActionCard) }
}
} }
private val DEFAULT_STATE: AutoFillState = AutoFillState( private val DEFAULT_STATE: AutoFillState = AutoFillState(
@ -473,4 +509,6 @@ private val DEFAULT_STATE: AutoFillState = AutoFillState(
showInlineAutofillOption = true, showInlineAutofillOption = true,
showPasskeyManagementRow = true, showPasskeyManagementRow = true,
defaultUriMatchType = UriMatchType.DOMAIN, defaultUriMatchType = UriMatchType.DOMAIN,
showAutofillActionCard = false,
activeUserId = "activeUserId",
) )

View file

@ -3,6 +3,7 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.autofill
import android.os.Build import android.os.Build
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import app.cash.turbine.test import app.cash.turbine.test
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow
@ -15,6 +16,7 @@ import io.mockk.runs
import io.mockk.unmockkStatic import io.mockk.unmockkStatic
import io.mockk.verify import io.mockk.verify
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertEquals
@ -25,6 +27,11 @@ class AutoFillViewModelTest : BaseViewModelTest() {
private val mutableIsAccessibilityEnabledStateFlow = MutableStateFlow(false) private val mutableIsAccessibilityEnabledStateFlow = MutableStateFlow(false)
private val mutableIsAutofillEnabledStateFlow = MutableStateFlow(false) private val mutableIsAutofillEnabledStateFlow = MutableStateFlow(false)
private val authRepository: AuthRepository = mockk {
every { userStateFlow.value?.activeUserId } returns "activeUserId"
}
private val mutableShowAutofillActionCardFlow = MutableStateFlow(false)
private val settingsRepository: SettingsRepository = mockk { private val settingsRepository: SettingsRepository = mockk {
every { isInlineAutofillEnabled } returns true every { isInlineAutofillEnabled } returns true
every { isInlineAutofillEnabled = any() } just runs every { isInlineAutofillEnabled = any() } just runs
@ -37,6 +44,8 @@ class AutoFillViewModelTest : BaseViewModelTest() {
every { isAccessibilityEnabledStateFlow } returns mutableIsAccessibilityEnabledStateFlow every { isAccessibilityEnabledStateFlow } returns mutableIsAccessibilityEnabledStateFlow
every { isAutofillEnabledStateFlow } returns mutableIsAutofillEnabledStateFlow every { isAutofillEnabledStateFlow } returns mutableIsAutofillEnabledStateFlow
every { disableAutofill() } just runs every { disableAutofill() } just runs
every { getShowAutofillBadgeFlow(any()) } returns mutableShowAutofillActionCardFlow
every { storeShowAutoFillSettingBadge(any(), any()) } just runs
} }
@BeforeEach @BeforeEach
@ -196,6 +205,40 @@ class AutoFillViewModelTest : BaseViewModelTest() {
) )
} }
@Test
fun `on AutoFillServicesClick should update show autofill in repository if card shown`() {
mutableShowAutofillActionCardFlow.update { true }
val viewModel = createViewModel()
assertEquals(
DEFAULT_STATE.copy(showAutofillActionCard = true),
viewModel.stateFlow.value,
)
viewModel.trySendAction(AutoFillAction.AutoFillServicesClick(true))
verify(exactly = 1) {
settingsRepository.storeShowAutoFillSettingBadge(
DEFAULT_STATE.activeUserId,
false,
)
}
}
@Suppress("MaxLineLength")
@Test
fun `on AutoFillServicesClick should not update show autofill in repository if card not shown`() {
val viewModel = createViewModel()
assertEquals(
DEFAULT_STATE.copy(showAutofillActionCard = false),
viewModel.stateFlow.value,
)
viewModel.trySendAction(AutoFillAction.AutoFillServicesClick(true))
verify(exactly = 0) {
settingsRepository.storeShowAutoFillSettingBadge(
DEFAULT_STATE.activeUserId,
false,
)
}
}
@Test @Test
fun `on BackClick should emit NavigateBack`() = runTest { fun `on BackClick should emit NavigateBack`() = runTest {
val viewModel = createViewModel() val viewModel = createViewModel()
@ -266,11 +309,50 @@ class AutoFillViewModelTest : BaseViewModelTest() {
} }
} }
@Test
fun `when showAutofillBadgeFlow updates value, should update state`() = runTest {
val viewModel = createViewModel()
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem())
mutableShowAutofillActionCardFlow.emit(true)
assertEquals(DEFAULT_STATE.copy(showAutofillActionCard = true), awaitItem())
}
}
@Suppress("MaxLineLength")
@Test
fun `when AutoFillActionCardCtaClick action is sent should update show autofill in repository`() {
mutableShowAutofillActionCardFlow.update { true }
val viewModel = createViewModel()
viewModel.trySendAction(AutoFillAction.AutoFillActionCardCtaClick)
verify {
settingsRepository.storeShowAutoFillSettingBadge(
DEFAULT_STATE.activeUserId,
false,
)
}
}
@Suppress("MaxLineLength")
@Test
fun `when DismissShowAutofillActionCard action is sent should update show autofill in repository`() {
mutableShowAutofillActionCardFlow.update { true }
val viewModel = createViewModel()
viewModel.trySendAction(AutoFillAction.DismissShowAutofillActionCard)
verify {
settingsRepository.storeShowAutoFillSettingBadge(
DEFAULT_STATE.activeUserId,
false,
)
}
}
private fun createViewModel( private fun createViewModel(
state: AutoFillState? = DEFAULT_STATE, state: AutoFillState? = DEFAULT_STATE,
): AutoFillViewModel = AutoFillViewModel( ): AutoFillViewModel = AutoFillViewModel(
savedStateHandle = SavedStateHandle().apply { set("state", state) }, savedStateHandle = SavedStateHandle().apply { set("state", state) },
settingsRepository = settingsRepository, settingsRepository = settingsRepository,
authRepository = authRepository,
) )
} }
@ -283,4 +365,6 @@ private val DEFAULT_STATE: AutoFillState = AutoFillState(
showInlineAutofillOption = false, showInlineAutofillOption = false,
showPasskeyManagementRow = true, showPasskeyManagementRow = true,
defaultUriMatchType = UriMatchType.DOMAIN, defaultUriMatchType = UriMatchType.DOMAIN,
showAutofillActionCard = false,
activeUserId = "activeUserId",
) )