diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt index 87d14d150..50850fa2c 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt @@ -52,6 +52,11 @@ interface SettingsRepository { */ val isUnlockWithPinEnabled: Boolean + /** + * Whether or not inline autofill is enabled for the current user. + */ + var isInlineAutofillEnabled: Boolean + /** * Sets default values for various settings for the given [userId] if necessary. This is * typically used when logging into a new account. diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt index 8456ca512..72c9a1f1a 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt @@ -97,6 +97,18 @@ class SettingsRepositoryImpl( ?.let { authDiskSource.getEncryptedPin(userId = it) != null } ?: false + override var isInlineAutofillEnabled: Boolean + get() = activeUserId + ?.let { settingsDiskSource.getInlineAutofillEnabled(userId = it) } + ?: true + set(value) { + val userId = activeUserId ?: return + settingsDiskSource.storeInlineAutofillEnabled( + userId = userId, + isInlineAutofillEnabled = value, + ) + } + override fun setDefaultsIfNecessary(userId: String) { // Set Vault Settings defaults if (!isVaultTimeoutActionSet(userId = userId)) { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModel.kt index 8ed66b26c..2405d7c04 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModel.kt @@ -4,6 +4,7 @@ import android.os.Parcelable import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import com.x8bit.bitwarden.R +import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.util.Text import com.x8bit.bitwarden.ui.platform.base.util.asText @@ -23,6 +24,7 @@ private const val KEY_STATE = "state" @HiltViewModel class AutoFillViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, + private val settingsRepository: SettingsRepository, ) : BaseViewModel( initialState = savedStateHandle[KEY_STATE] ?: AutoFillState( @@ -31,7 +33,7 @@ class AutoFillViewModel @Inject constructor( isCopyTotpAutomaticallyEnabled = false, isUseAccessibilityEnabled = false, isUseDrawOverEnabled = false, - isUseInlineAutoFillEnabled = false, + isUseInlineAutoFillEnabled = settingsRepository.isInlineAutofillEnabled, uriDetectionMethod = AutoFillState.UriDetectionMethod.DEFAULT, ), ) { @@ -90,8 +92,7 @@ class AutoFillViewModel @Inject constructor( } private fun handleUseInlineAutofillClick(action: AutoFillAction.UseInlineAutofillClick) { - // TODO BIT-833: Persist selection - sendEvent(AutoFillEvent.ShowToast("Not yet implemented.".asText())) + settingsRepository.isInlineAutofillEnabled = action.isEnabled mutableStateFlow.update { it.copy(isUseInlineAutoFillEnabled = action.isEnabled) } } diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt index e7250bde5..7d75454c9 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt @@ -341,6 +341,21 @@ class SettingsRepositoryTest { assertTrue(settingsRepository.isUnlockWithPinEnabled) } + @Test + fun `isInlineAutofillEnabled should pull from and update SettingsDiskSource`() { + val userId = "userId" + fakeAuthDiskSource.userState = MOCK_USER_STATE + assertTrue(settingsRepository.isInlineAutofillEnabled) + + // Updates to the disk source change the repository value. + fakeSettingsDiskSource.isIconLoadingDisabled = false + assertFalse(settingsRepository.isUnlockWithPinEnabled) + + // Updates to the repository change the disk source value + settingsRepository.isInlineAutofillEnabled = true + assertTrue(fakeSettingsDiskSource.getInlineAutofillEnabled(userId = userId)!!) + } + @Test fun `getPullToRefreshEnabledFlow should react to changes in SettingsDiskSource`() = runTest { val userId = "userId" diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModelTest.kt index 72257121c..ccd2aff5e 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillViewModelTest.kt @@ -2,14 +2,25 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.autofill import androidx.lifecycle.SavedStateHandle import app.cash.turbine.test +import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest import com.x8bit.bitwarden.ui.platform.base.util.asText +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.runs +import io.mockk.verify import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test class AutoFillViewModelTest : BaseViewModelTest() { + private val settingsRepository: SettingsRepository = mockk() { + every { isInlineAutofillEnabled } returns true + every { isInlineAutofillEnabled = any() } just runs + } + @Test fun `initial state should be correct when not set`() { val viewModel = createViewModel(state = null) @@ -103,16 +114,14 @@ class AutoFillViewModelTest : BaseViewModelTest() { } @Test - fun `on UseInlineAutofillClick should emit ShowToast`() = runTest { + fun `on UseInlineAutofillClick should update the state and save the new value to settings`() { val viewModel = createViewModel() - viewModel.eventFlow.test { - viewModel.trySendAction(AutoFillAction.UseInlineAutofillClick(true)) - assertEquals(AutoFillEvent.ShowToast("Not yet implemented.".asText()), awaitItem()) - } + viewModel.trySendAction(AutoFillAction.UseInlineAutofillClick(false)) assertEquals( - DEFAULT_STATE.copy(isUseInlineAutoFillEnabled = true), + DEFAULT_STATE.copy(isUseInlineAutoFillEnabled = false), viewModel.stateFlow.value, ) + verify { settingsRepository.isInlineAutofillEnabled = false } } @Test @@ -133,6 +142,7 @@ class AutoFillViewModelTest : BaseViewModelTest() { state: AutoFillState? = DEFAULT_STATE, ): AutoFillViewModel = AutoFillViewModel( savedStateHandle = SavedStateHandle().apply { set("state", state) }, + settingsRepository = settingsRepository, ) } @@ -142,6 +152,6 @@ private val DEFAULT_STATE: AutoFillState = AutoFillState( isCopyTotpAutomaticallyEnabled = false, isUseAccessibilityEnabled = false, isUseDrawOverEnabled = false, - isUseInlineAutoFillEnabled = false, + isUseInlineAutoFillEnabled = true, uriDetectionMethod = AutoFillState.UriDetectionMethod.DEFAULT, )