diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/FirstTimeActionManagerImpl.kt b/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/FirstTimeActionManagerImpl.kt index df5fcbbbe3..a1e2b70c7b 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/FirstTimeActionManagerImpl.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/FirstTimeActionManagerImpl.kt @@ -7,7 +7,6 @@ import com.x8bit.bitwarden.data.autofill.manager.AutofillEnabledManager import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource import com.x8bit.bitwarden.data.platform.manager.model.CoachMarkTourType import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState -import com.x8bit.bitwarden.data.platform.manager.model.FlagKey import com.x8bit.bitwarden.data.vault.datasource.disk.VaultDiskSource import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -31,7 +30,6 @@ class FirstTimeActionManagerImpl @Inject constructor( private val authDiskSource: AuthDiskSource, private val settingsDiskSource: SettingsDiskSource, private val vaultDiskSource: VaultDiskSource, - private val featureFlagManager: FeatureFlagManager, private val autofillEnabledManager: AutofillEnabledManager, ) : FirstTimeActionManager { @@ -101,16 +99,9 @@ class FirstTimeActionManagerImpl @Inject constructor( .activeUserIdChangesFlow .filterNotNull() .flatMapLatest { - combine( - getShowImportLoginsSettingBadgeFlowInternal(userId = it), - featureFlagManager.getFeatureFlagFlow(FlagKey.ImportLoginsFlow), - ) { showImportLogins, importLoginsEnabled -> - val shouldShowImportLoginsSettings = showImportLogins && importLoginsEnabled - listOf(shouldShowImportLoginsSettings) - } - .map { list -> - list.count { showImportLogins -> showImportLogins } - } + getShowImportLoginsSettingBadgeFlowInternal(userId = it) + .map { showImportLogins -> listOf(showImportLogins) } + .map { list -> list.count { showImportLogins -> showImportLogins } } } .stateIn( scope = unconfinedScope, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt b/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt index 9dbdce2d4e..efbb751d36 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt @@ -353,14 +353,12 @@ object PlatformManagerModule { settingsDiskSource: SettingsDiskSource, vaultDiskSource: VaultDiskSource, dispatcherManager: DispatcherManager, - featureFlagManager: FeatureFlagManager, autofillEnabledManager: AutofillEnabledManager, ): FirstTimeActionManager = FirstTimeActionManagerImpl( authDiskSource = authDiskSource, settingsDiskSource = settingsDiskSource, vaultDiskSource = vaultDiskSource, dispatcherManager = dispatcherManager, - featureFlagManager = featureFlagManager, autofillEnabledManager = autofillEnabledManager, ) diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt b/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt index 23145758ab..337ed39cac 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt @@ -22,7 +22,6 @@ sealed class FlagKey { val activeFlags: List> by lazy { listOf( EmailVerification, - ImportLoginsFlow, CredentialExchangeProtocolImport, CredentialExchangeProtocolExport, SingleTapPasskeyCreation, @@ -42,14 +41,6 @@ sealed class FlagKey { override val defaultValue: Boolean = false } - /** - * Data object holding the feature flag key for the import logins feature. - */ - data object ImportLoginsFlow : FlagKey() { - override val keyName: String = "import-logins-flow" - override val defaultValue: Boolean = false - } - /** * Data object holding hte feature flag key for the Credential Exchange Protocol (CXP) import * feature. diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/components/FeatureFlagListItems.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/components/FeatureFlagListItems.kt index 10939b069d..9b2249cc80 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/components/FeatureFlagListItems.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/components/FeatureFlagListItems.kt @@ -26,7 +26,6 @@ fun FlagKey.ListItemContent( } FlagKey.EmailVerification, - FlagKey.ImportLoginsFlow, FlagKey.CredentialExchangeProtocolImport, FlagKey.CredentialExchangeProtocolExport, FlagKey.CipherKeyEncryption, @@ -77,7 +76,6 @@ private fun FlagKey.getDisplayLabel(): String = when (this) { -> this.keyName FlagKey.EmailVerification -> stringResource(BitwardenString.email_verification) - FlagKey.ImportLoginsFlow -> stringResource(BitwardenString.import_logins_flow) FlagKey.CredentialExchangeProtocolImport -> stringResource(BitwardenString.cxp_import) FlagKey.CredentialExchangeProtocolExport -> stringResource(BitwardenString.cxp_export) FlagKey.CipherKeyEncryption -> stringResource(BitwardenString.cipher_key_encryption) diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreen.kt index 84a431f3e3..653c792e55 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreen.kt @@ -21,7 +21,6 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.core.net.toUri import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bitwarden.ui.platform.base.util.EventsEffect @@ -34,13 +33,10 @@ import com.bitwarden.ui.platform.resource.BitwardenDrawable import com.bitwarden.ui.platform.resource.BitwardenString 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.row.BitwardenExternalLinkRow import com.x8bit.bitwarden.ui.platform.components.row.BitwardenTextRow import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold import com.x8bit.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarHost import com.x8bit.bitwarden.ui.platform.components.snackbar.rememberBitwardenSnackbarHostState -import com.x8bit.bitwarden.ui.platform.composition.LocalIntentManager -import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager /** * Displays the vault settings screen. @@ -54,7 +50,6 @@ fun VaultSettingsScreen( onNavigateToFolders: () -> Unit, onNavigateToImportLogins: () -> Unit, viewModel: VaultSettingsViewModel = hiltViewModel(), - intentManager: IntentManager = LocalIntentManager.current, ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() @@ -64,14 +59,7 @@ fun VaultSettingsScreen( VaultSettingsEvent.NavigateBack -> onNavigateBack() VaultSettingsEvent.NavigateToExportVault -> onNavigateToExportVault() VaultSettingsEvent.NavigateToFolders -> onNavigateToFolders() - is VaultSettingsEvent.NavigateToImportVault -> { - if (state.isNewImportLoginsFlowEnabled) { - onNavigateToImportLogins() - } else { - intentManager.launchUri(event.url.toUri()) - } - } - + is VaultSettingsEvent.NavigateToImportVault -> onNavigateToImportLogins() is VaultSettingsEvent.ShowSnackbar -> snackbarHostState.showSnackbar(event.data) } } @@ -105,7 +93,7 @@ fun VaultSettingsScreen( ) { Spacer(modifier = Modifier.height(12.dp)) AnimatedVisibility( - visible = state.shouldShowImportCard, + visible = state.showImportActionCard, label = "ImportLoginsActionCard", exit = actionCardExitAnimation(), ) { @@ -159,38 +147,18 @@ fun VaultSettingsScreen( .fillMaxWidth(), ) - if (state.isNewImportLoginsFlowEnabled) { - BitwardenTextRow( - text = stringResource(BitwardenString.import_items), - onClick = remember(viewModel) { - { viewModel.trySendAction(VaultSettingsAction.ImportItemsClick) } - }, - withDivider = false, - cardStyle = CardStyle.Bottom, - modifier = Modifier - .testTag("ImportItemsLinkItemView") - .standardHorizontalMargin() - .fillMaxWidth(), - ) - } else { - BitwardenExternalLinkRow( - text = stringResource(BitwardenString.import_items), - onConfirmClick = remember(viewModel) { - { viewModel.trySendAction(VaultSettingsAction.ImportItemsClick) } - }, - withDivider = false, - dialogTitle = stringResource(id = BitwardenString.continue_to_web_app), - dialogMessage = stringResource( - id = BitwardenString.you_can_import_data_to_your_vault_on_x, - state.importUrl, - ), - cardStyle = CardStyle.Bottom, - modifier = Modifier - .testTag("ImportItemsLinkItemView") - .standardHorizontalMargin() - .fillMaxWidth(), - ) - } + BitwardenTextRow( + text = stringResource(BitwardenString.import_items), + onClick = remember(viewModel) { + { viewModel.trySendAction(VaultSettingsAction.ImportItemsClick) } + }, + withDivider = false, + cardStyle = CardStyle.Bottom, + modifier = Modifier + .testTag("ImportItemsLinkItemView") + .standardHorizontalMargin() + .fillMaxWidth(), + ) Spacer(modifier = Modifier.height(height = 16.dp)) Spacer(modifier = Modifier.navigationBarsPadding()) } diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsViewModel.kt index 0cd0bef56a..fccbe4f005 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsViewModel.kt @@ -1,13 +1,9 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.vault import androidx.lifecycle.viewModelScope -import com.bitwarden.data.repository.util.toBaseWebVaultImportUrl import com.bitwarden.ui.platform.base.BackgroundEvent import com.bitwarden.ui.platform.base.BaseViewModel -import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager -import com.x8bit.bitwarden.data.platform.manager.model.FlagKey -import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository import com.x8bit.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarData import com.x8bit.bitwarden.ui.platform.manager.snackbar.SnackbarRelay import com.x8bit.bitwarden.ui.platform.manager.snackbar.SnackbarRelayManager @@ -24,31 +20,17 @@ import javax.inject.Inject @Suppress("TooManyFunctions") @HiltViewModel class VaultSettingsViewModel @Inject constructor( - environmentRepository: EnvironmentRepository, - featureFlagManager: FeatureFlagManager, snackbarRelayManager: SnackbarRelayManager, private val firstTimeActionManager: FirstTimeActionManager, ) : BaseViewModel( initialState = run { val firstTimeState = firstTimeActionManager.currentOrDefaultUserFirstTimeState VaultSettingsState( - importUrl = environmentRepository - .environment - .environmentUrlData - .toBaseWebVaultImportUrl, - isNewImportLoginsFlowEnabled = featureFlagManager - .getFeatureFlag(FlagKey.ImportLoginsFlow), showImportActionCard = firstTimeState.showImportLoginsCardInSettings, ) }, ) { init { - featureFlagManager - .getFeatureFlagFlow(FlagKey.ImportLoginsFlow) - .map { VaultSettingsAction.Internal.ImportLoginsFeatureFlagChanged(it) } - .onEach(::sendAction) - .launchIn(viewModelScope) - firstTimeActionManager .firstTimeStateFlow .map { @@ -78,10 +60,6 @@ class VaultSettingsViewModel @Inject constructor( private fun handleInternalAction(action: VaultSettingsAction.Internal) { when (action) { - is VaultSettingsAction.Internal.ImportLoginsFeatureFlagChanged -> { - handleImportLoginsFeatureFlagChanged(action) - } - is VaultSettingsAction.Internal.UserFirstTimeStateChanged -> { handleUserFirstTimeStateChanged(action) } @@ -99,12 +77,12 @@ class VaultSettingsViewModel @Inject constructor( } private fun handleImportLoginsCardDismissClicked() { - if (!state.shouldShowImportCard) return + if (!state.showImportActionCard) return firstTimeActionManager.storeShowImportLoginsSettingsBadge(showBadge = false) } private fun handleImportLoginsCardClicked() { - sendEvent(VaultSettingsEvent.NavigateToImportVault(state.importUrl)) + sendEvent(VaultSettingsEvent.NavigateToImportVault) } private fun handleUserFirstTimeStateChanged( @@ -115,14 +93,6 @@ class VaultSettingsViewModel @Inject constructor( } } - private fun handleImportLoginsFeatureFlagChanged( - action: VaultSettingsAction.Internal.ImportLoginsFeatureFlagChanged, - ) { - mutableStateFlow.update { - it.copy(isNewImportLoginsFlowEnabled = action.isEnabled) - } - } - private fun handleBackClicked() { sendEvent(VaultSettingsEvent.NavigateBack) } @@ -136,9 +106,7 @@ class VaultSettingsViewModel @Inject constructor( } private fun handleImportItemsClicked() { - sendEvent( - VaultSettingsEvent.NavigateToImportVault(state.importUrl), - ) + sendEvent(VaultSettingsEvent.NavigateToImportVault) } } @@ -146,16 +114,8 @@ class VaultSettingsViewModel @Inject constructor( * Models the state for the VaultSettingScreen. */ data class VaultSettingsState( - val importUrl: String, - val isNewImportLoginsFlowEnabled: Boolean, - private val showImportActionCard: Boolean, -) { - /** - * Should only show the import action card if the import logins feature flag is enabled. - */ - val shouldShowImportCard: Boolean - get() = showImportActionCard && isNewImportLoginsFlowEnabled -} + val showImportActionCard: Boolean, +) /** * Models events for the vault screen. @@ -169,7 +129,7 @@ sealed class VaultSettingsEvent { /** * Navigate to the import vault URL. */ - data class NavigateToImportVault(val url: String) : VaultSettingsEvent() + data object NavigateToImportVault : VaultSettingsEvent() /** * Navigate to the Export Vault screen. @@ -225,14 +185,6 @@ sealed class VaultSettingsAction { * Internal actions not performed by user interation */ sealed class Internal : VaultSettingsAction() { - - /** - * Indicates that the import logins feature flag has changed. - */ - data class ImportLoginsFeatureFlagChanged( - val isEnabled: Boolean, - ) : Internal() - /** * Indicates user first time state has changed. */ diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt index 7f10b68883..1636c2af20 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt @@ -164,14 +164,7 @@ class VaultViewModel @Inject constructor( authRepository .userStateFlow - .combine( - featureFlagManager.getFeatureFlagFlow(FlagKey.ImportLoginsFlow), - ) { userState, importLoginsEnabled -> - VaultAction.Internal.UserStateUpdateReceive( - userState = userState, - importLoginsFlowEnabled = importLoginsEnabled, - ) - } + .map { VaultAction.Internal.UserStateUpdateReceive(it) } .onEach(::sendAction) .launchIn(viewModelScope) @@ -805,8 +798,6 @@ class VaultViewModel @Inject constructor( .any(), ) val appBarTitle = vaultFilterData.toAppBarTitle() - val shouldShowImportActionCard = action.importLoginsFlowEnabled && - firstTimeState.showImportLoginsCard mutableStateFlow.update { val accountSummaries = userState.toAccountSummaries() @@ -818,7 +809,7 @@ class VaultViewModel @Inject constructor( accountSummaries = accountSummaries, vaultFilterData = vaultFilterData, isPremium = userState.activeAccount.isPremium, - showImportActionCard = shouldShowImportActionCard, + showImportActionCard = firstTimeState.showImportLoginsCard, ) } } @@ -1704,7 +1695,6 @@ sealed class VaultAction { */ data class UserStateUpdateReceive( val userState: UserState?, - val importLoginsFlowEnabled: Boolean, ) : Internal() /** diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/FirstTimeActionManagerTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/FirstTimeActionManagerTest.kt index a22ccec8e3..86e7a53a3e 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/FirstTimeActionManagerTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/FirstTimeActionManagerTest.kt @@ -14,7 +14,6 @@ import com.x8bit.bitwarden.data.autofill.manager.AutofillEnabledManager import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeSettingsDiskSource import com.x8bit.bitwarden.data.platform.manager.model.CoachMarkTourType import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState -import com.x8bit.bitwarden.data.platform.manager.model.FlagKey import com.x8bit.bitwarden.data.vault.datasource.disk.VaultDiskSource import io.mockk.every import io.mockk.mockk @@ -35,13 +34,6 @@ class FirstTimeActionManagerTest { private val vaultDiskSource = mockk { every { getCiphersFlow(any()) } returns mutableCiphersListFlow } - - private val mutableImportLoginsFlow = MutableStateFlow(false) - private val mutableOnboardingFeatureFlow = MutableStateFlow(false) - private val featureFlagManager = mockk { - every { getFeatureFlagFlow(FlagKey.ImportLoginsFlow) } returns mutableImportLoginsFlow - } - private val mutableAutofillEnabledFlow = MutableStateFlow(false) private val autofillEnabledManager = mockk { every { isAutofillEnabledStateFlow } returns mutableAutofillEnabledFlow @@ -52,14 +44,13 @@ class FirstTimeActionManagerTest { authDiskSource = fakeAuthDiskSource, settingsDiskSource = fakeSettingsDiskSource, vaultDiskSource = vaultDiskSource, - featureFlagManager = featureFlagManager, dispatcherManager = FakeDispatcherManager(), autofillEnabledManager = autofillEnabledManager, ) @Suppress("MaxLineLength") @Test - fun `allAutoFillSettingsBadgeCountFlow should emit the value of flags set to true and update when saved value is changed or autofill enabled state changes`() = + fun `allAutoFillSettingsBadgeCountFlow should update when saved value is changed or autofill enabled state changes`() = runTest { fakeAuthDiskSource.userState = MOCK_USER_STATE firstTimeActionManager.allAutofillSettingsBadgeCountFlow.test { @@ -84,81 +75,66 @@ class FirstTimeActionManagerTest { } } - @Suppress("MaxLineLength") @Test - fun `allSecuritySettingsBadgeCountFlow should emit the value of flags set to true and update when changed`() = - runTest { - fakeAuthDiskSource.userState = MOCK_USER_STATE - firstTimeActionManager.allSecuritySettingsBadgeCountFlow.test { - assertEquals(0, awaitItem()) - fakeSettingsDiskSource.storeShowUnlockSettingBadge( - userId = USER_ID, - showBadge = true, - ) - assertEquals(1, awaitItem()) - fakeSettingsDiskSource.storeShowUnlockSettingBadge( - userId = USER_ID, - showBadge = false, - ) - assertEquals(0, awaitItem()) - } + fun `allSecuritySettingsBadgeCountFlow should update when changed`() = runTest { + fakeAuthDiskSource.userState = MOCK_USER_STATE + firstTimeActionManager.allSecuritySettingsBadgeCountFlow.test { + assertEquals(0, awaitItem()) + fakeSettingsDiskSource.storeShowUnlockSettingBadge( + userId = USER_ID, + showBadge = true, + ) + assertEquals(1, awaitItem()) + fakeSettingsDiskSource.storeShowUnlockSettingBadge( + userId = USER_ID, + showBadge = false, + ) + assertEquals(0, awaitItem()) } + } - @Suppress("MaxLineLength") @Test - fun `allSettingsBadgeCountFlow should emit the value of all flags set to true and update when changed`() = - runTest { - fakeAuthDiskSource.userState = MOCK_USER_STATE - firstTimeActionManager.allSettingsBadgeCountFlow.test { - assertEquals(0, awaitItem()) - fakeSettingsDiskSource.storeShowAutoFillSettingBadge( - userId = USER_ID, - showBadge = true, - ) - assertEquals(1, awaitItem()) - fakeSettingsDiskSource.storeShowUnlockSettingBadge( - userId = USER_ID, - showBadge = true, - ) - assertEquals(2, awaitItem()) - fakeSettingsDiskSource.storeShowAutoFillSettingBadge( - userId = USER_ID, - showBadge = false, - ) - assertEquals(1, awaitItem()) - // for the import logins count it is dependent on the feature flag state and - // cipher list being empty - mutableImportLoginsFlow.update { true } - fakeSettingsDiskSource.storeShowImportLoginsSettingBadge(USER_ID, true) - assertEquals(2, awaitItem()) - } + fun `allSettingsBadgeCountFlow should update when changed`() = runTest { + fakeAuthDiskSource.userState = MOCK_USER_STATE + firstTimeActionManager.allSettingsBadgeCountFlow.test { + assertEquals(0, awaitItem()) + fakeSettingsDiskSource.storeShowAutoFillSettingBadge( + userId = USER_ID, + showBadge = true, + ) + assertEquals(1, awaitItem()) + fakeSettingsDiskSource.storeShowUnlockSettingBadge( + userId = USER_ID, + showBadge = true, + ) + assertEquals(2, awaitItem()) + fakeSettingsDiskSource.storeShowAutoFillSettingBadge( + userId = USER_ID, + showBadge = false, + ) + assertEquals(1, awaitItem()) + // for the import logins count it is dependent on the cipher list being empty + fakeSettingsDiskSource.storeShowImportLoginsSettingBadge(USER_ID, true) + assertEquals(2, awaitItem()) } + } - @Suppress("MaxLineLength") @Test - fun `allVaultSettingsBadgeCountFlow should emit the value of all flags set to true and update when dependent states are changed changed`() = + fun `allVaultSettingsBadgeCountFlow should update when dependent states are changed changed`() = runTest { fakeAuthDiskSource.userState = MOCK_USER_STATE val mockCipher = mockk(relaxed = true) - // For the import logins count to register, the feature flag for ImportLoginsFlow must - // be enabled, the cipher list must not be empty, and the value saved to disk should be - // true. + // For the import logins count to register, the cipher list must not be empty, and the + // value saved to disk should be true. firstTimeActionManager.allVaultSettingsBadgeCountFlow.test { assertEquals(0, awaitItem()) - mutableImportLoginsFlow.update { true } fakeSettingsDiskSource.storeShowImportLoginsSettingBadge(USER_ID, true) assertEquals(1, awaitItem()) - mutableImportLoginsFlow.update { false } - assertEquals(0, awaitItem()) - mutableImportLoginsFlow.update { true } - assertEquals(1, awaitItem()) fakeSettingsDiskSource.storeShowImportLoginsSettingBadge(USER_ID, false) assertEquals(0, awaitItem()) fakeSettingsDiskSource.storeShowImportLoginsSettingBadge(USER_ID, true) assertEquals(1, awaitItem()) - mutableCiphersListFlow.update { - listOf(mockCipher) - } + mutableCiphersListFlow.update { listOf(mockCipher) } assertEquals(0, awaitItem()) } } @@ -167,8 +143,7 @@ class FirstTimeActionManagerTest { fun `firstTimeStateFlow should emit changes when items in the first time state change`() = runTest { firstTimeActionManager.firstTimeStateFlow.test { - fakeAuthDiskSource.userState = - MOCK_USER_STATE + fakeAuthDiskSource.userState = MOCK_USER_STATE assertEquals( FirstTimeState( showImportLoginsCard = true, @@ -208,40 +183,35 @@ class FirstTimeActionManagerTest { @Test fun `storeShowAutoFillSettingBadge should store value of false to disk`() { - fakeAuthDiskSource.userState = - MOCK_USER_STATE + fakeAuthDiskSource.userState = MOCK_USER_STATE firstTimeActionManager.storeShowAutoFillSettingBadge(showBadge = false) assertFalse(fakeSettingsDiskSource.getShowAutoFillSettingBadge(userId = USER_ID)!!) } @Test fun `storeShowAutoFillSettingBadge should store value of true to disk`() { - fakeAuthDiskSource.userState = - MOCK_USER_STATE + fakeAuthDiskSource.userState = MOCK_USER_STATE firstTimeActionManager.storeShowAutoFillSettingBadge(showBadge = true) assertTrue(fakeSettingsDiskSource.getShowAutoFillSettingBadge(userId = USER_ID)!!) } @Test fun `getShowAutoFillSettingBadge should return the value saved to disk`() { - fakeAuthDiskSource.userState = - MOCK_USER_STATE + fakeAuthDiskSource.userState = MOCK_USER_STATE firstTimeActionManager.storeShowAutoFillSettingBadge(showBadge = true) assertTrue(fakeSettingsDiskSource.getShowAutoFillSettingBadge(userId = USER_ID)!!) } @Test fun `storeShowUnlockSettingBadge should store value of false to disk`() { - fakeAuthDiskSource.userState = - MOCK_USER_STATE + fakeAuthDiskSource.userState = MOCK_USER_STATE firstTimeActionManager.storeShowUnlockSettingBadge(showBadge = false) assertFalse(fakeSettingsDiskSource.getShowUnlockSettingBadge(userId = USER_ID)!!) } @Test fun `storeShowUnlockSettingBadge should store value of true to disk`() { - fakeAuthDiskSource.userState = - MOCK_USER_STATE + fakeAuthDiskSource.userState = MOCK_USER_STATE firstTimeActionManager.storeShowUnlockSettingBadge(showBadge = true) assertTrue(fakeSettingsDiskSource.getShowUnlockSettingBadge(userId = USER_ID)!!) } @@ -303,8 +273,6 @@ class FirstTimeActionManagerTest { @Test fun `shouldShowAddLoginCoachMarkFlow updates when disk source updates`() = runTest { fakeAuthDiskSource.userState = MOCK_USER_STATE - // Enable the feature for this test. - mutableOnboardingFeatureFlow.update { true } firstTimeActionManager.shouldShowAddLoginCoachMarkFlow.test { assertTrue(awaitItem()) fakeSettingsDiskSource.storeShouldShowAddLoginCoachMark(shouldShow = false) @@ -325,8 +293,6 @@ class FirstTimeActionManagerTest { every { organizationId } returns null } fakeAuthDiskSource.userState = MOCK_USER_STATE - // Enable feature flag so flow emits updates from disk. - mutableOnboardingFeatureFlow.update { true } mutableCiphersListFlow.update { listOf( mockJsonWithNoLogin, @@ -356,8 +322,6 @@ class FirstTimeActionManagerTest { @Test fun `shouldShowGeneratorCoachMarkFlow updates when disk source updates`() = runTest { fakeAuthDiskSource.userState = MOCK_USER_STATE - // Enable feature flag so flow emits updates from disk. - mutableOnboardingFeatureFlow.update { true } firstTimeActionManager.shouldShowGeneratorCoachMarkFlow.test { assertTrue(awaitItem()) fakeSettingsDiskSource.storeShouldShowGeneratorCoachMark(shouldShow = false) @@ -378,8 +342,6 @@ class FirstTimeActionManagerTest { every { organizationId } returns null } fakeAuthDiskSource.userState = MOCK_USER_STATE - // Enable feature flag so flow emits updates from disk. - mutableOnboardingFeatureFlow.update { true } mutableCiphersListFlow.update { listOf( mockJsonWithNoLogin, @@ -406,8 +368,6 @@ class FirstTimeActionManagerTest { every { organizationId } returns "1234" } fakeAuthDiskSource.userState = MOCK_USER_STATE - // Enable feature flag so flow emits updates from disk. - mutableOnboardingFeatureFlow.update { true } mutableCiphersListFlow.update { listOf(mockJsonWithLoginAndWithOrganizationId) } diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/FlagKeyTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/FlagKeyTest.kt index 46fa13e37a..ce0e0af2d7 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/FlagKeyTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/FlagKeyTest.kt @@ -13,10 +13,6 @@ class FlagKeyTest { FlagKey.EmailVerification.keyName, "email-verification", ) - assertEquals( - FlagKey.ImportLoginsFlow.keyName, - "import-logins-flow", - ) assertEquals( FlagKey.CredentialExchangeProtocolImport.keyName, "cxp-import-mobile", @@ -56,7 +52,6 @@ class FlagKeyTest { assertTrue( listOf( FlagKey.EmailVerification, - FlagKey.ImportLoginsFlow, FlagKey.CredentialExchangeProtocolImport, FlagKey.CredentialExchangeProtocolExport, FlagKey.SingleTapPasskeyCreation, diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuViewModelTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuViewModelTest.kt index 68ce557700..9d0e7e0c1b 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuViewModelTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuViewModelTest.kt @@ -145,7 +145,6 @@ class DebugMenuViewModelTest : BaseViewModelTest() { private val DEFAULT_MAP_VALUE: ImmutableMap, Any> = persistentMapOf( FlagKey.EmailVerification to true, - FlagKey.ImportLoginsFlow to true, FlagKey.CredentialExchangeProtocolImport to true, FlagKey.CredentialExchangeProtocolExport to true, FlagKey.SingleTapPasskeyCreation to true, @@ -157,7 +156,6 @@ private val DEFAULT_MAP_VALUE: ImmutableMap, Any> = persistentMapOf private val UPDATED_MAP_VALUE: ImmutableMap, Any> = persistentMapOf( FlagKey.EmailVerification to false, - FlagKey.ImportLoginsFlow to false, FlagKey.CredentialExchangeProtocolImport to false, FlagKey.CredentialExchangeProtocolExport to false, FlagKey.SingleTapPasskeyCreation to false, diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreenTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreenTest.kt index 7b4fbdbf17..ecbc66bc5f 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreenTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreenTest.kt @@ -1,20 +1,15 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.vault -import androidx.compose.ui.test.assert import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.assertIsNotDisplayed -import androidx.compose.ui.test.hasAnyAncestor -import androidx.compose.ui.test.isDialog import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollTo -import androidx.core.net.toUri import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.ui.util.asText import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest import com.x8bit.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarData -import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import io.mockk.every import io.mockk.just import io.mockk.mockk @@ -22,7 +17,6 @@ import io.mockk.runs import io.mockk.verify import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update -import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test @@ -36,14 +30,9 @@ class VaultSettingsScreenTest : BitwardenComposeTest() { private val mutableEventFlow = bufferedMutableSharedFlow() private val mutableStateFlow = MutableStateFlow( VaultSettingsState( - importUrl = "testUrl/#/tools/import", - isNewImportLoginsFlowEnabled = false, showImportActionCard = false, ), ) - private val intentManager: IntentManager = mockk(relaxed = true) { - every { launchUri(any()) } just runs - } val viewModel = mockk(relaxed = true) { every { eventFlow } returns mutableEventFlow @@ -52,9 +41,7 @@ class VaultSettingsScreenTest : BitwardenComposeTest() { @Before fun setup() { - setContent( - intentManager = intentManager, - ) { + setContent { VaultSettingsScreen( viewModel = viewModel, onNavigateBack = { onNavigateBackCalled = true }, @@ -80,42 +67,6 @@ class VaultSettingsScreenTest : BitwardenComposeTest() { } } - @Test - fun `import items click should display dialog and confirming should send ImportItemsClick`() { - composeTestRule.onNodeWithText("Import items").performClick() - composeTestRule - .onNodeWithText("Continue") - .assert(hasAnyAncestor(isDialog())) - .assertIsDisplayed() - .performClick() - - verify { - viewModel.trySendAction(VaultSettingsAction.ImportItemsClick) - } - } - - @Test - fun `import items click should display dialog & canceling should not send ImportItemsClick`() { - composeTestRule.onNodeWithText("Import items").performClick() - composeTestRule - .onNodeWithText("Cancel") - .assert(hasAnyAncestor(isDialog())) - .assertIsDisplayed() - .performClick() - - verify(exactly = 0) { - viewModel.trySendAction(VaultSettingsAction.ImportItemsClick) - } - } - - @Test - fun `import items click should display dialog with importUrl`() { - composeTestRule.onNodeWithText("Import items").performClick() - composeTestRule - .onNodeWithText(mutableStateFlow.value.importUrl, substring = true) - .assertIsDisplayed() - } - @Test fun `NavigateBack should call onNavigateBack`() { mutableEventFlow.tryEmit(VaultSettingsEvent.NavigateBack) @@ -135,43 +86,20 @@ class VaultSettingsScreenTest : BitwardenComposeTest() { } @Test - fun `on NavigateToImportVault should invoke IntentManager not lambda`() { - val testUrl = "testUrl" - mutableEventFlow.tryEmit(VaultSettingsEvent.NavigateToImportVault(testUrl)) - verify { - intentManager.launchUri(testUrl.toUri()) - } - assertFalse(onNavigateToImportLoginsCalled) - } - - @Test - fun `when new logins feature flag is enabled send action right when import items is clicked`() { - mutableStateFlow.update { - it.copy(isNewImportLoginsFlowEnabled = true) - } + fun `send action right when import items is clicked`() { composeTestRule.onNodeWithText("Import items").performClick() verify { viewModel.trySendAction(VaultSettingsAction.ImportItemsClick) } } @Test - fun `when new logins feature flag is enabled NavigateToImportVault should invoke lambda`() { - mutableStateFlow.update { - it.copy(isNewImportLoginsFlowEnabled = true) - } - val testUrl = "testUrl" - mutableEventFlow.tryEmit(VaultSettingsEvent.NavigateToImportVault(testUrl)) + fun `NavigateToImportVault should invoke lambda`() { + mutableEventFlow.tryEmit(VaultSettingsEvent.NavigateToImportVault) assertTrue(onNavigateToImportLoginsCalled) - verify(exactly = 0) { intentManager.launchUri(testUrl.toUri()) } } @Test fun `when new show action card is true the import logins card should show`() { - mutableStateFlow.update { - it.copy( - showImportActionCard = true, - isNewImportLoginsFlowEnabled = true, - ) - } + mutableStateFlow.update { it.copy(showImportActionCard = true) } composeTestRule .onNodeWithText("Import saved logins") .performScrollTo() @@ -186,12 +114,7 @@ class VaultSettingsScreenTest : BitwardenComposeTest() { @Test fun `when action card is visible clicking the close icon should send correct action`() { - mutableStateFlow.update { - it.copy( - showImportActionCard = true, - isNewImportLoginsFlowEnabled = true, - ) - } + mutableStateFlow.update { it.copy(showImportActionCard = true) } composeTestRule .onNodeWithContentDescription("Close") .performScrollTo() @@ -203,12 +126,7 @@ class VaultSettingsScreenTest : BitwardenComposeTest() { @Test fun `when action card is visible get started button should send correct action`() { - mutableStateFlow.update { - it.copy( - showImportActionCard = true, - isNewImportLoginsFlowEnabled = true, - ) - } + mutableStateFlow.update { it.copy(showImportActionCard = true) } composeTestRule .onNodeWithText("Get started") .performScrollTo() diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsViewModelTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsViewModelTest.kt index 6b44bd631a..ea9782e1dd 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsViewModelTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsViewModelTest.kt @@ -4,11 +4,8 @@ import app.cash.turbine.test import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.ui.platform.base.BaseViewModelTest import com.bitwarden.ui.util.asText -import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState -import com.x8bit.bitwarden.data.platform.manager.model.FlagKey -import com.x8bit.bitwarden.data.platform.repository.util.FakeEnvironmentRepository import com.x8bit.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarData import com.x8bit.bitwarden.ui.platform.manager.snackbar.SnackbarRelay import com.x8bit.bitwarden.ui.platform.manager.snackbar.SnackbarRelayManager @@ -26,12 +23,6 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test class VaultSettingsViewModelTest : BaseViewModelTest() { - private val environmentRepository = FakeEnvironmentRepository() - private val mutableImportLoginsFlagFlow = MutableStateFlow(false) - private val featureFlagManager = mockk { - every { getFeatureFlagFlow(FlagKey.ImportLoginsFlow) } returns mutableImportLoginsFlagFlow - every { getFeatureFlag(FlagKey.ImportLoginsFlow) } returns false - } private val mutableFirstTimeStateFlow = MutableStateFlow(DEFAULT_FIRST_TIME_STATE) private val firstTimeActionManager = mockk { every { currentOrDefaultUserFirstTimeState } returns DEFAULT_FIRST_TIME_STATE @@ -68,44 +59,25 @@ class VaultSettingsViewModelTest : BaseViewModelTest() { } @Test - fun `ImportItemsClick should emit send NavigateToImportVault with correct url`() = runTest { + fun `ImportItemsClick should emit send NavigateToImportVault`() = runTest { val viewModel = createViewModel() - val expected = "https://vault.bitwarden.com/#/tools/import" viewModel.eventFlow.test { viewModel.trySendAction(VaultSettingsAction.ImportItemsClick) assertEquals( - VaultSettingsEvent.NavigateToImportVault(expected), + VaultSettingsEvent.NavigateToImportVault, awaitItem(), ) } } - @Test - fun `ImportLoginsFeatureFlagChanged should update state`() { - val viewModel = createViewModel() - assertFalse( - viewModel.stateFlow.value.isNewImportLoginsFlowEnabled, - ) - mutableImportLoginsFlagFlow.update { true } - assertTrue(viewModel.stateFlow.value.isNewImportLoginsFlowEnabled) - } - @Test fun `shouldShowImportCard should update when first time state changes`() = runTest { - mutableImportLoginsFlagFlow.update { true } val viewModel = createViewModel() - assertTrue(viewModel.stateFlow.value.shouldShowImportCard) + assertTrue(viewModel.stateFlow.value.showImportActionCard) mutableFirstTimeStateFlow.update { it.copy(showImportLoginsCardInSettings = false) } - assertFalse(viewModel.stateFlow.value.shouldShowImportCard) - } - - @Test - fun `shouldShowImportCard should be false when feature flag not enabled`() = runTest { - val viewModel = createViewModel() - mutableImportLoginsFlagFlow.update { false } - assertFalse(viewModel.stateFlow.value.shouldShowImportCard) + assertFalse(viewModel.stateFlow.value.showImportActionCard) } @Suppress("MaxLineLength") @@ -113,12 +85,10 @@ class VaultSettingsViewModelTest : BaseViewModelTest() { fun `ImportLoginsCardCtaClick action should set repository value to false and send navigation event`() = runTest { val viewModel = createViewModel() - val expected = "https://vault.bitwarden.com/#/tools/import" - mutableImportLoginsFlagFlow.update { true } viewModel.eventFlow.test { viewModel.trySendAction(VaultSettingsAction.ImportLoginsCardCtaClick) assertEquals( - VaultSettingsEvent.NavigateToImportVault(url = expected), + VaultSettingsEvent.NavigateToImportVault, awaitItem(), ) } @@ -129,7 +99,6 @@ class VaultSettingsViewModelTest : BaseViewModelTest() { @Test fun `ImportLoginsCardDismissClick action should set repository value to false `() = runTest { - mutableImportLoginsFlagFlow.update { true } val viewModel = createViewModel() viewModel.trySendAction(VaultSettingsAction.ImportLoginsCardDismissClick) verify(exactly = 1) { @@ -141,6 +110,7 @@ class VaultSettingsViewModelTest : BaseViewModelTest() { @Test fun `ImportLoginsCardDismissClick action should not set repository value to false if already false`() = runTest { + mutableFirstTimeStateFlow.update { it.copy(showImportLoginsCardInSettings = false) } val viewModel = createViewModel() viewModel.trySendAction(VaultSettingsAction.ImportLoginsCardDismissClick) verify(exactly = 0) { @@ -159,8 +129,6 @@ class VaultSettingsViewModelTest : BaseViewModelTest() { } private fun createViewModel(): VaultSettingsViewModel = VaultSettingsViewModel( - environmentRepository = environmentRepository, - featureFlagManager = featureFlagManager, firstTimeActionManager = firstTimeActionManager, snackbarRelayManager = snackbarRelayManager, ) diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt index b090367f14..3bb1c7969b 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt @@ -73,7 +73,6 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.update import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.AfterEach @@ -172,13 +171,9 @@ class VaultViewModelTest : BaseViewModelTest() { every { trackEvent(event = any()) } just runs } - private val mutableImportLoginsFeatureFlow = MutableStateFlow(true) private val mutableRemoveCardPolicyFeatureFlow = MutableStateFlow(false) private val mutableSshKeyVaultItemsEnabledFlow = MutableStateFlow(false) private val featureFlagManager: FeatureFlagManager = mockk { - every { - getFeatureFlagFlow(FlagKey.ImportLoginsFlow) - } returns mutableImportLoginsFeatureFlow every { getFeatureFlagFlow(FlagKey.RemoveCardPolicy) } returns mutableRemoveCardPolicyFeatureFlow @@ -2433,30 +2428,6 @@ class VaultViewModelTest : BaseViewModelTest() { } } - @Suppress("MaxLineLength") - @Test - fun `when feature flag ImportLoginsFlow is disabled, should show action card should always be false`() = - runTest { - mutableImportLoginsFeatureFlow.update { false } - val viewModel = createViewModel() - viewModel.stateFlow.test { - assertEquals( - DEFAULT_STATE.copy(showImportActionCard = false), - awaitItem(), - ) - mutableUserStateFlow.value = DEFAULT_USER_STATE.copy( - accounts = DEFAULT_USER_STATE.accounts.map { - it.copy( - firstTimeState = DEFAULT_FIRST_TIME_STATE.copy( - showImportLoginsCard = true, - ), - ) - }, - ) - expectNoEvents() - } - } - @Suppress("MaxLineLength") @Test fun `when DismissImportActionCard is sent, repository called to showImportLogins to false and storeShowImportLoginsBadge to true`() { diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml index fc40a39ed1..13fc401881 100644 --- a/ui/src/main/res/values/strings.xml +++ b/ui/src/main/res/values/strings.xml @@ -672,7 +672,6 @@ Do you want to switch to this account? Continue to device Settings? Make your account more secure by setting up two-step login in the Bitwarden web app. You can change your master password on the Bitwarden web app. - You can import data to your vault on %1$s. Learn more about how to use Bitwarden on the Help center. Check out our privacy policy on bitwarden.com. Explore more features of your Bitwarden account on the web app. diff --git a/ui/src/main/res/values/strings_non_localized.xml b/ui/src/main/res/values/strings_non_localized.xml index 8bd8b0a3a6..84b10e23dc 100644 --- a/ui/src/main/res/values/strings_non_localized.xml +++ b/ui/src/main/res/values/strings_non_localized.xml @@ -9,7 +9,6 @@ Email Verification - Import Logins Flow Feature Flags: Debug Menu Reset values