diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/AddEditBlockedUriDialog.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/AddEditBlockedUriDialog.kt index c8790f199e..0ae8ff8a2e 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/AddEditBlockedUriDialog.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/AddEditBlockedUriDialog.kt @@ -42,7 +42,6 @@ fun AddEditBlockedUriDialog( onUriChange: (String) -> Unit, onCancelClick: () -> Unit, onSaveClick: (String) -> Unit, - onDeleteClick: (() -> Unit)? = null, onDismissRequest: () -> Unit, ) { Dialog( @@ -66,7 +65,13 @@ fun AddEditBlockedUriDialog( modifier = Modifier .padding(top = 24.dp, start = 24.dp, end = 24.dp) .fillMaxWidth(), - text = stringResource(id = BitwardenString.new_uri), + text = stringResource( + id = if (isEdit) { + BitwardenString.edit_blocked_uri + } else { + BitwardenString.new_blocked_uri + }, + ), color = BitwardenTheme.colorScheme.text.primary, style = BitwardenTheme.typography.headlineSmall, ) @@ -104,13 +109,6 @@ fun AddEditBlockedUriDialog( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(start = 8.dp, top = 24.dp, bottom = 24.dp, end = 24.dp), ) { - if (isEdit && onDeleteClick != null) { - BitwardenTextButton( - label = stringResource(id = BitwardenString.remove), - onClick = onDeleteClick, - ) - } - BitwardenTextButton( label = stringResource(id = BitwardenString.cancel), onClick = onCancelClick, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreen.kt index 1909e8b97e..e900f0383a 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreen.kt @@ -4,8 +4,6 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.scaleIn import androidx.compose.animation.scaleOut import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -17,17 +15,17 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState -import androidx.compose.material3.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -38,18 +36,24 @@ import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bitwarden.ui.platform.base.util.EventsEffect -import com.bitwarden.ui.platform.base.util.bottomDivider +import com.bitwarden.ui.platform.base.util.cardStyle +import com.bitwarden.ui.platform.base.util.standardHorizontalMargin +import com.bitwarden.ui.platform.base.util.toListItemCardStyle import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar -import com.bitwarden.ui.platform.components.button.BitwardenOutlinedButton +import com.bitwarden.ui.platform.components.appbar.action.BitwardenOverflowActionItem +import com.bitwarden.ui.platform.components.appbar.model.OverflowMenuItemData +import com.bitwarden.ui.platform.components.button.BitwardenFilledButton import com.bitwarden.ui.platform.components.fab.BitwardenFloatingActionButton +import com.bitwarden.ui.platform.components.model.CardStyle import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold import com.bitwarden.ui.platform.components.util.rememberVectorPainter import com.bitwarden.ui.platform.resource.BitwardenDrawable import com.bitwarden.ui.platform.resource.BitwardenString import com.bitwarden.ui.platform.theme.BitwardenTheme +import kotlinx.collections.immutable.persistentListOf /** - * Displays the block auto-fill screen. + * Displays the block autofill screen. */ @Suppress("LongMethod") @OptIn(ExperimentalMaterial3Api::class) @@ -74,7 +78,6 @@ fun BlockAutoFillScreen( BlockAutoFillAction.SaveUri(newUri = newUri, originalUri = originalUri), ) }, - onRemoveClick = { viewModel.trySendAction(BlockAutoFillAction.RemoveUriClick(it)) }, onDismissRequest = { viewModel.trySendAction(BlockAutoFillAction.DismissDialog) }, ) @@ -107,84 +110,94 @@ fun BlockAutoFillScreen( } }, ) { - LazyColumn( - modifier = Modifier.fillMaxSize(), - ) { - when (val viewState = state.viewState) { - is BlockAutoFillState.ViewState.Content -> { - item { - Row( - modifier = Modifier - .padding(vertical = 8.dp, horizontal = 20.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center, - ) { - Text( - text = stringResource( - id = BitwardenString - .auto_fill_will_not_be_offered_for_these_ur_is, - ), - color = BitwardenTheme.colorScheme.text.primary, - style = BitwardenTheme.typography.bodyMedium, - modifier = Modifier.align(Alignment.CenterVertically), - ) - } - } - - items(viewState.blockedUris, key = { it }) { uri -> - BlockAutoFillListItem( - label = uri, - onClick = { - viewModel.trySendAction(BlockAutoFillAction.EditUriClick(uri)) - }, - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), - ) - } - } - - is BlockAutoFillState.ViewState.Empty -> { - item { - BlockAutoFillNoItems( - addItemClickAction = { - viewModel.trySendAction(BlockAutoFillAction.AddUriClick) - }, - modifier = Modifier.fillMaxSize(), - ) - } - } + when (val viewState = state.viewState) { + is BlockAutoFillState.ViewState.Content -> { + BlockedAutofillContent( + viewState = viewState, + onEditUriClick = { + viewModel.trySendAction(BlockAutoFillAction.EditUriClick(it)) + }, + onRemoveClick = { + viewModel.trySendAction(BlockAutoFillAction.RemoveUriClick(it)) + }, + modifier = Modifier.fillMaxSize(), + ) } - item { - Spacer(modifier = Modifier.height(height = 16.dp)) - Spacer(modifier = Modifier.navigationBarsPadding()) + + BlockAutoFillState.ViewState.Empty -> { + BlockAutoFillNoItems( + addItemClickAction = { + viewModel.trySendAction(BlockAutoFillAction.AddUriClick) + }, + modifier = Modifier.fillMaxSize(), + ) } } } } +@Composable +private fun BlockedAutofillContent( + viewState: BlockAutoFillState.ViewState.Content, + onEditUriClick: (String) -> Unit, + onRemoveClick: (String) -> Unit, + modifier: Modifier = Modifier, +) { + LazyColumn(modifier = modifier) { + item { + Spacer(modifier = Modifier.height(height = 24.dp)) + Text( + text = stringResource( + id = BitwardenString.auto_fill_will_not_be_offered_for_these_ur_is, + ), + textAlign = TextAlign.Center, + color = BitwardenTheme.colorScheme.text.secondary, + style = BitwardenTheme.typography.bodyMedium, + modifier = Modifier + .fillMaxWidth() + .standardHorizontalMargin() + .animateItem(), + ) + Spacer(modifier = Modifier.height(height = 24.dp)) + } + + itemsIndexed( + items = viewState.blockedUris, + key = { _, uri -> uri }, + ) { index, uri -> + BlockAutoFillListItem( + label = uri, + onDeleteClick = { onRemoveClick(uri) }, + onEditClick = { onEditUriClick(uri) }, + cardStyle = viewState.blockedUris.toListItemCardStyle(index = index), + modifier = Modifier + .standardHorizontalMargin() + .fillMaxWidth() + .animateItem(), + ) + } + item { + Spacer(modifier = Modifier.height(height = 16.dp)) + Spacer(modifier = Modifier.navigationBarsPadding()) + } + } +} + @Composable private fun BlockAutoFillDialogs( dialogState: BlockAutoFillState.DialogState? = null, onUriTextChange: (String) -> Unit, onSaveClick: (String, String?) -> Unit, - onRemoveClick: (String) -> Unit, onDismissRequest: () -> Unit, ) { when (dialogState) { is BlockAutoFillState.DialogState.AddEdit -> { AddEditBlockedUriDialog( uri = dialogState.uri, - isEdit = dialogState.originalUri != null, + isEdit = dialogState.isEdit, errorMessage = dialogState.errorMessage?.invoke(), onUriChange = onUriTextChange, onDismissRequest = onDismissRequest, - onDeleteClick = if (dialogState.isEdit) { - { dialogState.originalUri?.let { onRemoveClick(it) } } - } else { - null - }, onCancelClick = onDismissRequest, onSaveClick = { newUri -> onSaveClick(newUri, dialogState.originalUri) }, ) @@ -203,7 +216,7 @@ private fun BlockAutoFillNoItems( modifier: Modifier = Modifier, ) { Column( - modifier = modifier, + modifier = modifier.verticalScroll(state = rememberScrollState()), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -217,66 +230,87 @@ private fun BlockAutoFillNoItems( .size(size = 124.dp) .align(Alignment.CenterHorizontally), ) - Spacer(modifier = Modifier.height(32.dp)) + Spacer(modifier = Modifier.height(height = 24.dp)) Text( textAlign = TextAlign.Center, + text = stringResource(id = BitwardenString.no_uris_blocked), + style = BitwardenTheme.typography.titleMedium, + color = BitwardenTheme.colorScheme.text.primary, modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp), + .standardHorizontalMargin(), + ) + + Spacer(modifier = Modifier.height(height = 12.dp)) + + Text( + textAlign = TextAlign.Center, text = stringResource( id = BitwardenString.auto_fill_will_not_be_offered_for_these_ur_is, ), style = BitwardenTheme.typography.bodyMedium, + color = BitwardenTheme.colorScheme.text.primary, + modifier = Modifier + .fillMaxWidth() + .standardHorizontalMargin(), ) Spacer(modifier = Modifier.height(24.dp)) - BitwardenOutlinedButton( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), + BitwardenFilledButton( label = stringResource(id = BitwardenString.new_blocked_uri), onClick = addItemClickAction, + icon = rememberVectorPainter(id = BitwardenDrawable.ic_plus_small), + modifier = Modifier + .wrapContentWidth() + .standardHorizontalMargin(), ) + Spacer(modifier = Modifier.height(height = 24.dp)) + Spacer(modifier = Modifier.navigationBarsPadding()) } } @Composable private fun BlockAutoFillListItem( label: String, - onClick: () -> Unit, + onEditClick: () -> Unit, + onDeleteClick: () -> Unit, + cardStyle: CardStyle, modifier: Modifier = Modifier, ) { Row( - modifier = Modifier - .defaultMinSize(minHeight = 60.dp) - .clickable( - interactionSource = remember { MutableInteractionSource() }, - indication = ripple( - color = BitwardenTheme.colorScheme.background.pressed, - ), - onClick = onClick, - ) - .bottomDivider(paddingStart = 16.dp) - .padding(end = 8.dp, top = 16.dp, bottom = 16.dp) - .then(modifier), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, + modifier = modifier + .defaultMinSize(minHeight = 60.dp) + .cardStyle( + cardStyle = cardStyle, + paddingStart = 16.dp, + paddingEnd = 4.dp, + ), ) { Text( - modifier = Modifier - .padding(end = 16.dp) - .weight(1f), text = label, style = BitwardenTheme.typography.bodyLarge, color = BitwardenTheme.colorScheme.text.primary, + modifier = Modifier + .padding(end = 16.dp) + .weight(weight = 1f), ) - Icon( - painter = rememberVectorPainter(id = BitwardenDrawable.ic_pencil_square), - contentDescription = null, - tint = BitwardenTheme.colorScheme.icon.primary, - modifier = Modifier.size(24.dp), + BitwardenOverflowActionItem( + menuItemDataList = persistentListOf( + OverflowMenuItemData( + text = stringResource(id = BitwardenString.edit), + onClick = onEditClick, + ), + OverflowMenuItemData( + text = stringResource(id = BitwardenString.delete), + onClick = onDeleteClick, + ), + ), + vectorIconRes = BitwardenDrawable.ic_ellipsis_horizontal, + testTag = "Options", ) } } diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillViewModel.kt index 63ab805f4c..e77945fe10 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillViewModel.kt @@ -10,6 +10,9 @@ import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.blockautofill.util.isValidPattern import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.blockautofill.util.validateUri import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.update import kotlinx.parcelize.Parcelize import javax.inject.Inject @@ -40,7 +43,9 @@ class BlockAutoFillViewModel @Inject constructor( mutableStateFlow.update { currentState -> if (uris.isNotEmpty()) { currentState.copy( - viewState = BlockAutoFillState.ViewState.Content(uris.map { it }), + viewState = BlockAutoFillState.ViewState.Content( + blockedUris = uris.distinct().toImmutableList(), + ), ) } else { currentState.copy( @@ -163,7 +168,7 @@ class BlockAutoFillViewModel @Inject constructor( } /** - * Represents the state for block auto fill. + * Represents the state for block autofill. * * @property viewState indicates what view state the screen is in. */ @@ -203,7 +208,7 @@ data class BlockAutoFillState( */ @Parcelize data class Content( - val blockedUris: List = emptyList(), + val blockedUris: ImmutableList = persistentListOf(), ) : ViewState() /** diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreenTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreenTest.kt index 69bc3c2f3e..968eaecc5b 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreenTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreenTest.kt @@ -11,10 +11,12 @@ import androidx.compose.ui.test.performScrollTo import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.ui.util.asText import com.bitwarden.ui.util.assertNoDialogExists +import com.bitwarden.ui.util.assertNoPopupExists import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest import io.mockk.every import io.mockk.mockk import io.mockk.verify +import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.flow.MutableStateFlow import org.junit.Assert.assertTrue import org.junit.Before @@ -68,7 +70,7 @@ class BlockAutoFillScreenTest : BitwardenComposeTest() { @Test fun `Screen should display content state view when in ViewState Content`() { mutableStateFlow.value = BlockAutoFillState( - viewState = BlockAutoFillState.ViewState.Content(listOf("uri1", "uri2")), + viewState = BlockAutoFillState.ViewState.Content(persistentListOf("uri1", "uri2")), ) listOf("uri1", "uri2").forEach { uri -> @@ -109,17 +111,6 @@ class BlockAutoFillScreenTest : BitwardenComposeTest() { verify { viewModel.trySendAction(BlockAutoFillAction.AddUriClick) } } - @Test - fun `on URI item click should send EditUriClick`() { - mutableStateFlow.value = BlockAutoFillState( - viewState = BlockAutoFillState.ViewState.Content(listOf("uri1")), - ) - - composeTestRule.onNodeWithText("uri1").performClick() - - verify { viewModel.trySendAction(BlockAutoFillAction.EditUriClick(uri = "uri1")) } - } - @Test fun `should show add URI dialog according to state`() { composeTestRule.assertNoDialogExists() @@ -130,33 +121,36 @@ class BlockAutoFillScreenTest : BitwardenComposeTest() { originalUri = null, errorMessage = null, ), - viewState = BlockAutoFillState.ViewState.Content(listOf("uri1")), + viewState = BlockAutoFillState.ViewState.Content(persistentListOf("uri1")), ) composeTestRule - .onNodeWithText("New URI") + .onNodeWithText("New blocked URI") .assert(hasAnyAncestor(isDialog())) } @Test - fun `clicking a uri from the list should send EditUriClick action`() { - val testUri = "http://test.com" - - composeTestRule.assertNoDialogExists() + fun `clicking edit in popup menu should send EditUriClick action`() { + composeTestRule.assertNoPopupExists() + val uriToRemove = "http://uriToRemove.com" mutableStateFlow.value = BlockAutoFillState( - dialog = BlockAutoFillState.DialogState.AddEdit( - uri = testUri, - originalUri = testUri, - errorMessage = null, + viewState = BlockAutoFillState.ViewState.Content( + blockedUris = persistentListOf(uriToRemove), ), - viewState = BlockAutoFillState.ViewState.Content(listOf("uri1")), ) composeTestRule - .onNodeWithText("New URI") - .assert(hasAnyAncestor(isDialog())) - .assertIsDisplayed() + .onNodeWithContentDescription(label = "More options") + .performScrollTo() + .performClick() + + composeTestRule + .onNodeWithText(text = "Edit") + .performScrollTo() + .performClick() + + verify { viewModel.trySendAction(BlockAutoFillAction.EditUriClick(uri = uriToRemove)) } } @Test @@ -171,7 +165,7 @@ class BlockAutoFillScreenTest : BitwardenComposeTest() { originalUri = null, errorMessage = errorMessage.asText(), ), - viewState = BlockAutoFillState.ViewState.Content(listOf("uri1")), + viewState = BlockAutoFillState.ViewState.Content(persistentListOf("uri1")), ) composeTestRule @@ -190,7 +184,7 @@ class BlockAutoFillScreenTest : BitwardenComposeTest() { originalUri = null, errorMessage = null, ), - viewState = BlockAutoFillState.ViewState.Content(listOf("existingUri")), + viewState = BlockAutoFillState.ViewState.Content(persistentListOf("existingUri")), ) val newUri = "http://newuri.com" @@ -209,7 +203,7 @@ class BlockAutoFillScreenTest : BitwardenComposeTest() { originalUri = null, errorMessage = null, ), - viewState = BlockAutoFillState.ViewState.Content(emptyList()), + viewState = BlockAutoFillState.ViewState.Content(persistentListOf()), ) composeTestRule.onNodeWithText("Cancel").performClick() @@ -218,20 +212,25 @@ class BlockAutoFillScreenTest : BitwardenComposeTest() { } @Test - fun `clicking remove in dialog should send RemoveUriClick action`() { - composeTestRule.assertNoDialogExists() + fun `clicking delete in popup menu should send RemoveUriClick action`() { + composeTestRule.assertNoPopupExists() val uriToRemove = "http://uriToRemove.com" mutableStateFlow.value = BlockAutoFillState( - dialog = BlockAutoFillState.DialogState.AddEdit( - uri = uriToRemove, - originalUri = uriToRemove, - errorMessage = null, + viewState = BlockAutoFillState.ViewState.Content( + blockedUris = persistentListOf(uriToRemove), ), - viewState = BlockAutoFillState.ViewState.Content(listOf(uriToRemove, "otherUri")), ) - composeTestRule.onNodeWithText("Remove").performClick() + composeTestRule + .onNodeWithContentDescription(label = "More options") + .performScrollTo() + .performClick() + + composeTestRule + .onNodeWithText(text = "Delete") + .performScrollTo() + .performClick() verify { viewModel.trySendAction(BlockAutoFillAction.RemoveUriClick(uri = uriToRemove)) } } diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillViewModelTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillViewModelTest.kt index 6de569f2e6..c702e47d1f 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillViewModelTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillViewModelTest.kt @@ -8,6 +8,8 @@ import com.bitwarden.ui.util.asText import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import io.mockk.every import io.mockk.mockk +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test @@ -24,7 +26,7 @@ class BlockAutoFillViewModelTest : BaseViewModelTest() { val viewModel = createViewModel() val expectedState = BlockAutoFillState( viewState = BlockAutoFillState.ViewState.Content( - blockedUris = listOf("blockedUri"), + blockedUris = persistentListOf("blockedUri"), ), ) @@ -64,7 +66,9 @@ class BlockAutoFillViewModelTest : BaseViewModelTest() { originalUri = null, errorMessage = null, ), - viewState = BlockAutoFillState.ViewState.Content(blockedUris = listOf("blockedUri")), + viewState = BlockAutoFillState.ViewState.Content( + blockedUris = persistentListOf("blockedUri"), + ), ) assertEquals(expectedState, viewModel.stateFlow.value) @@ -82,7 +86,7 @@ class BlockAutoFillViewModelTest : BaseViewModelTest() { originalUri = testUri, errorMessage = null, ), - viewState = BlockAutoFillState.ViewState.Content(listOf("blockedUri")), + viewState = BlockAutoFillState.ViewState.Content(persistentListOf("blockedUri")), ) assertEquals(expectedState, viewModel.stateFlow.value) @@ -104,7 +108,7 @@ class BlockAutoFillViewModelTest : BaseViewModelTest() { val expectedState = BlockAutoFillState( dialog = null, viewState = BlockAutoFillState.ViewState.Content( - blockedUris = listOf("http://b.com"), + blockedUris = persistentListOf("http://b.com"), ), ) @@ -128,7 +132,7 @@ class BlockAutoFillViewModelTest : BaseViewModelTest() { val expectedState = BlockAutoFillState( dialog = null, viewState = BlockAutoFillState.ViewState.Content( - blockedUris = blockedUris, + blockedUris = blockedUris.toImmutableList(), ), ) @@ -152,7 +156,11 @@ class BlockAutoFillViewModelTest : BaseViewModelTest() { val expectedState = BlockAutoFillState( dialog = null, viewState = BlockAutoFillState.ViewState.Content( - blockedUris = listOf("http://existing.com", "http://new.com", "http://another.com"), + blockedUris = persistentListOf( + "http://existing.com", + "http://new.com", + "http://another.com", + ), ), ) @@ -189,7 +197,7 @@ class BlockAutoFillViewModelTest : BaseViewModelTest() { val expectedState = BlockAutoFillState( dialog = null, viewState = BlockAutoFillState.ViewState.Content( - blockedUris = listOf("http://other.com", "http://new.com"), + blockedUris = persistentListOf("http://other.com", "http://new.com"), ), ) @@ -217,7 +225,7 @@ class BlockAutoFillViewModelTest : BaseViewModelTest() { val expectedState = BlockAutoFillState( dialog = null, viewState = BlockAutoFillState.ViewState.Content( - blockedUris = listOf("http://other.com", "http://same.com"), + blockedUris = persistentListOf("http://other.com", "http://same.com"), ), ) @@ -249,7 +257,7 @@ class BlockAutoFillViewModelTest : BaseViewModelTest() { errorMessage = BitwardenString.the_urix_is_already_blocked.asText("http://b.com"), ), viewState = BlockAutoFillState.ViewState.Content( - blockedUris = listOf("http://a.com", "http://b.com"), + blockedUris = persistentListOf("http://a.com", "http://b.com"), ), ) diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml index 7e730a253d..44d2dae339 100644 --- a/ui/src/main/res/values/strings.xml +++ b/ui/src/main/res/values/strings.xml @@ -295,7 +295,6 @@ Scanning will happen automatically. Text What type of custom field do you want to add? Remove - New URI Add website Base domain Default (%1$s) @@ -667,7 +666,9 @@ Do you want to switch to this account? You will be notified once approved. Trouble logging in? Block autofill + No URIs blocked Autofill will not be offered for these URIs. + Edit blocked URI New blocked URI Invalid format. Use https://, http://, or androidapp:// Enter URI