PM-13464 and PM-13627 support (#4107)

This commit is contained in:
Dave Severns 2024-10-17 13:30:13 -04:00 committed by GitHub
parent 5faa30e2f2
commit 56ad1ef05b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 662 additions and 357 deletions

View file

@ -45,6 +45,7 @@ import com.x8bit.bitwarden.data.auth.repository.model.AuthState
import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult
import com.x8bit.bitwarden.data.auth.repository.model.DeleteAccountResult import com.x8bit.bitwarden.data.auth.repository.model.DeleteAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.EmailTokenResult import com.x8bit.bitwarden.data.auth.repository.model.EmailTokenResult
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.KnownDeviceResult import com.x8bit.bitwarden.data.auth.repository.model.KnownDeviceResult
import com.x8bit.bitwarden.data.auth.repository.model.LoginResult import com.x8bit.bitwarden.data.auth.repository.model.LoginResult
import com.x8bit.bitwarden.data.auth.repository.model.NewSsoUserResult import com.x8bit.bitwarden.data.auth.repository.model.NewSsoUserResult
@ -76,8 +77,6 @@ import com.x8bit.bitwarden.data.auth.repository.util.SsoCallbackResult
import com.x8bit.bitwarden.data.auth.repository.util.WebAuthResult import com.x8bit.bitwarden.data.auth.repository.util.WebAuthResult
import com.x8bit.bitwarden.data.auth.repository.util.activeUserIdChangesFlow import com.x8bit.bitwarden.data.auth.repository.util.activeUserIdChangesFlow
import com.x8bit.bitwarden.data.auth.repository.util.currentOnboardingStatus import com.x8bit.bitwarden.data.auth.repository.util.currentOnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.util.currentOrDefaultUserFirstTimeState
import com.x8bit.bitwarden.data.auth.repository.util.firstTimeStateFlow
import com.x8bit.bitwarden.data.auth.repository.util.onboardingStatusChangesFlow import com.x8bit.bitwarden.data.auth.repository.util.onboardingStatusChangesFlow
import com.x8bit.bitwarden.data.auth.repository.util.policyInformation import com.x8bit.bitwarden.data.auth.repository.util.policyInformation
import com.x8bit.bitwarden.data.auth.repository.util.toRemovedPasswordUserStateJson import com.x8bit.bitwarden.data.auth.repository.util.toRemovedPasswordUserStateJson
@ -96,6 +95,7 @@ import com.x8bit.bitwarden.data.auth.util.YubiKeyResult
import com.x8bit.bitwarden.data.auth.util.toSdkParams import com.x8bit.bitwarden.data.auth.util.toSdkParams
import com.x8bit.bitwarden.data.platform.datasource.disk.ConfigDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.ConfigDiskSource
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.PolicyManager import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.PushManager import com.x8bit.bitwarden.data.platform.manager.PushManager
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
@ -164,6 +164,7 @@ class AuthRepositoryImpl(
private val userLogoutManager: UserLogoutManager, private val userLogoutManager: UserLogoutManager,
private val policyManager: PolicyManager, private val policyManager: PolicyManager,
private val featureFlagManager: FeatureFlagManager, private val featureFlagManager: FeatureFlagManager,
private val firstTimeActionManager: FirstTimeActionManager,
pushManager: PushManager, pushManager: PushManager,
dispatcherManager: DispatcherManager, dispatcherManager: DispatcherManager,
) : AuthRepository, ) : AuthRepository,
@ -258,7 +259,7 @@ class AuthRepositoryImpl(
authDiskSource.userOrganizationsListFlow, authDiskSource.userOrganizationsListFlow,
authDiskSource.userKeyConnectorStateFlow, authDiskSource.userKeyConnectorStateFlow,
authDiskSource.onboardingStatusChangesFlow, authDiskSource.onboardingStatusChangesFlow,
authDiskSource.firstTimeStateFlow, firstTimeActionManager.firstTimeStateFlow,
vaultRepository.vaultUnlockDataStateFlow, vaultRepository.vaultUnlockDataStateFlow,
mutableHasPendingAccountAdditionStateFlow, mutableHasPendingAccountAdditionStateFlow,
// Ignore the data in the merge, but trigger an update when they emit. // Ignore the data in the merge, but trigger an update when they emit.
@ -272,7 +273,7 @@ class AuthRepositoryImpl(
val userOrganizationsList = array[2] as List<UserOrganizations> val userOrganizationsList = array[2] as List<UserOrganizations>
val userIsUsingKeyConnectorList = array[3] as List<UserKeyConnectorState> val userIsUsingKeyConnectorList = array[3] as List<UserKeyConnectorState>
val onboardingStatus = array[4] as OnboardingStatus? val onboardingStatus = array[4] as OnboardingStatus?
val firstTimeState = array[5] as UserState.FirstTimeState val firstTimeState = array[5] as FirstTimeState
val vaultState = array[6] as List<VaultUnlockData> val vaultState = array[6] as List<VaultUnlockData>
val hasPendingAccountAddition = array[7] as Boolean val hasPendingAccountAddition = array[7] as Boolean
userStateJson?.toUserState( userStateJson?.toUserState(
@ -305,7 +306,7 @@ class AuthRepositoryImpl(
isBiometricsEnabledProvider = ::isBiometricsEnabled, isBiometricsEnabledProvider = ::isBiometricsEnabled,
vaultUnlockTypeProvider = ::getVaultUnlockType, vaultUnlockTypeProvider = ::getVaultUnlockType,
isDeviceTrustedProvider = ::isDeviceTrusted, isDeviceTrustedProvider = ::isDeviceTrusted,
firstTimeState = authDiskSource.currentOrDefaultUserFirstTimeState, firstTimeState = firstTimeActionManager.currentOrDefaultUserFirstTimeState,
), ),
) )

View file

@ -15,6 +15,7 @@ import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.AuthRepositoryImpl import com.x8bit.bitwarden.data.auth.repository.AuthRepositoryImpl
import com.x8bit.bitwarden.data.platform.datasource.disk.ConfigDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.ConfigDiskSource
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.PolicyManager import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.PushManager import com.x8bit.bitwarden.data.platform.manager.PushManager
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
@ -58,6 +59,7 @@ object AuthRepositoryModule {
pushManager: PushManager, pushManager: PushManager,
policyManager: PolicyManager, policyManager: PolicyManager,
featureFlagManager: FeatureFlagManager, featureFlagManager: FeatureFlagManager,
firstTimeActionManager: FirstTimeActionManager,
): AuthRepository = AuthRepositoryImpl( ): AuthRepository = AuthRepositoryImpl(
accountsService = accountsService, accountsService = accountsService,
devicesService = devicesService, devicesService = devicesService,
@ -79,5 +81,6 @@ object AuthRepositoryModule {
pushManager = pushManager, pushManager = pushManager,
policyManager = policyManager, policyManager = policyManager,
featureFlagManager = featureFlagManager, featureFlagManager = featureFlagManager,
firstTimeActionManager = firstTimeActionManager,
) )
} }

View file

@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.repository.model
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.model.UserState.Account import com.x8bit.bitwarden.data.auth.repository.model.UserState.Account
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.platform.repository.model.Environment import com.x8bit.bitwarden.data.platform.repository.model.Environment
/** /**
@ -95,21 +96,4 @@ data class UserState(
val hasLoginApprovingDevice: Boolean, val hasLoginApprovingDevice: Boolean,
val hasResetPasswordPermission: Boolean, val hasResetPasswordPermission: Boolean,
) )
/**
* Model to encapsulate different states for a user's first time experience.
*/
data class FirstTimeState(
val showImportLoginsCard: Boolean,
) {
/**
* Constructs a [FirstTimeState] accepting nullable values. If a value is null, the default
* is used.
*/
constructor(
showImportLoginsCoachMarker: Boolean?,
) : this(
showImportLoginsCard = showImportLoginsCoachMarker ?: true,
)
}
} }

View file

@ -5,7 +5,6 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.UserSwitchingData import com.x8bit.bitwarden.data.auth.repository.model.UserSwitchingData
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -192,42 +191,3 @@ val AuthDiskSource.currentOnboardingStatus: OnboardingStatus?
.userState .userState
?.activeUserId ?.activeUserId
?.let { this.getOnboardingStatus(userId = it) } ?.let { this.getOnboardingStatus(userId = it) }
/**
* Returns a [Flow] that emits every time the active user's first time state is changed.
*/
@OptIn(ExperimentalCoroutinesApi::class)
val AuthDiskSource.firstTimeStateFlow: Flow<UserState.FirstTimeState>
get() = activeUserIdChangesFlow
.flatMapLatest { activeUserId ->
combine(
listOf(
activeUserId
?.let {
getShowImportLoginsFlow(it)
}
?: flowOf(null),
),
) {
UserState.FirstTimeState(
showImportLoginsCoachMarker = it[0],
)
}
}
.distinctUntilChanged()
/**
* Get the current [UserState.FirstTimeState] of the active user if available, otherwise return
* a default configuration.
*/
val AuthDiskSource.currentOrDefaultUserFirstTimeState
get() = userState
?.activeUserId
?.let {
UserState.FirstTimeState(
showImportLoginsCoachMarker = getShowImportLogins(it),
)
}
?: UserState.FirstTimeState(
showImportLoginsCoachMarker = true,
)

View file

@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.repository.util
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.UserDecryptionOptionsJson import com.x8bit.bitwarden.data.auth.datasource.network.model.UserDecryptionOptionsJson
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
@ -111,7 +112,7 @@ fun UserStateJson.toUserState(
userIsUsingKeyConnectorList: List<UserKeyConnectorState>, userIsUsingKeyConnectorList: List<UserKeyConnectorState>,
hasPendingAccountAddition: Boolean, hasPendingAccountAddition: Boolean,
onboardingStatus: OnboardingStatus?, onboardingStatus: OnboardingStatus?,
firstTimeState: UserState.FirstTimeState, firstTimeState: FirstTimeState,
isBiometricsEnabledProvider: (userId: String) -> Boolean, isBiometricsEnabledProvider: (userId: String) -> Boolean,
vaultUnlockTypeProvider: (userId: String) -> VaultUnlockType, vaultUnlockTypeProvider: (userId: String) -> VaultUnlockType,
isDeviceTrustedProvider: (userId: String) -> Boolean, isDeviceTrustedProvider: (userId: String) -> Boolean,

View file

@ -0,0 +1,47 @@
package com.x8bit.bitwarden.data.platform.manager
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
/**
* Manager for compiling the state of all first time actions and related information such
* as counts of notifications to show, etc.
*/
interface FirstTimeActionManager {
/**
* Returns an observable count of the number of settings items that have a badge to display
* for the current active user.
*/
val allSettingsBadgeCountFlow: StateFlow<Int>
/**
* Returns an observable count of the number of security settings items that have a badge to
* display for the current active user.
*/
val allSecuritySettingsBadgeCountFlow: StateFlow<Int>
/**
* Returns an observable count of the number of autofill settings items that have a badge to
* display for the current active user.
*/
val allAutofillSettingsBadgeCountFlow: StateFlow<Int>
/**
* Returns an observable count of the number of vault settings items that have a badge to
* display for the current active user.
*/
val allVaultSettingsBadgeCountFlow: StateFlow<Int>
/**
* Returns a [Flow] that emits every time the active user's first time state is changed.
*/
val firstTimeStateFlow: Flow<FirstTimeState>
/**
* Get the current [FirstTimeState] of the active user if available, otherwise return
* a default configuration.
*/
val currentOrDefaultUserFirstTimeState: FirstTimeState
}

View file

@ -0,0 +1,186 @@
package com.x8bit.bitwarden.data.platform.manager
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
import com.x8bit.bitwarden.data.auth.repository.util.activeUserIdChangesFlow
import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
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
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import javax.inject.Inject
/**
* Implementation of [FirstTimeActionManager]
*/
class FirstTimeActionManagerImpl @Inject constructor(
dispatcherManager: DispatcherManager,
private val authDiskSource: AuthDiskSource,
private val settingsDiskSource: SettingsDiskSource,
private val vaultDiskSource: VaultDiskSource,
private val featureFlagManager: FeatureFlagManager,
) : FirstTimeActionManager {
private val unconfinedScope = CoroutineScope(dispatcherManager.unconfined)
override val allSettingsBadgeCountFlow: StateFlow<Int>
get() = combine(
listOf(
allSecuritySettingsBadgeCountFlow,
allAutofillSettingsBadgeCountFlow,
allVaultSettingsBadgeCountFlow,
),
) {
it.sum()
}
.stateIn(
scope = unconfinedScope,
started = SharingStarted.Lazily,
initialValue = 0,
)
@OptIn(ExperimentalCoroutinesApi::class)
override val allSecuritySettingsBadgeCountFlow: StateFlow<Int>
get() = authDiskSource
.activeUserIdChangesFlow
.filterNotNull()
.flatMapLatest {
// can be expanded to support multiple security settings
settingsDiskSource.getShowUnlockSettingBadgeFlow(userId = it)
.map { showUnlockBadge ->
listOfNotNull(showUnlockBadge)
}
.map { list ->
list.count { badgeOnValue -> badgeOnValue }
}
}
.stateIn(
scope = unconfinedScope,
started = SharingStarted.Lazily,
initialValue = 0,
)
@OptIn(ExperimentalCoroutinesApi::class)
override val allAutofillSettingsBadgeCountFlow: StateFlow<Int>
get() = authDiskSource
.activeUserIdChangesFlow
.filterNotNull()
.flatMapLatest {
// Can be expanded to support multiple autofill settings
settingsDiskSource.getShowAutoFillSettingBadgeFlow(userId = it)
.map { showAutofillBadge ->
listOfNotNull(showAutofillBadge)
}
.map { list ->
list.count { showBadge -> showBadge }
}
}
.stateIn(
scope = unconfinedScope,
started = SharingStarted.Lazily,
initialValue = 0,
)
@OptIn(ExperimentalCoroutinesApi::class)
override val allVaultSettingsBadgeCountFlow: StateFlow<Int>
get() = authDiskSource
.activeUserIdChangesFlow
.filterNotNull()
.flatMapLatest {
combine(
getShowImportLoginsFlowInternal(userId = it),
featureFlagManager.getFeatureFlagFlow(FlagKey.ImportLoginsFlow),
) { showImportLogins, importLoginsEnabled ->
val shouldShowImportLogins = showImportLogins && importLoginsEnabled
listOf(shouldShowImportLogins)
}
.map { list ->
list.count { showImportLogins -> showImportLogins }
}
}
.stateIn(
scope = unconfinedScope,
started = SharingStarted.Lazily,
initialValue = 0,
)
/**
* Returns a [Flow] that emits every time the active user's first time state is changed.
*/
@OptIn(ExperimentalCoroutinesApi::class)
override val firstTimeStateFlow: Flow<FirstTimeState>
get() = authDiskSource
.activeUserIdChangesFlow
.filterNotNull()
.flatMapLatest { activeUserId ->
combine(
listOf(
getShowImportLoginsFlowInternal(userId = activeUserId),
settingsDiskSource.getShowUnlockSettingBadgeFlow(userId = activeUserId),
settingsDiskSource.getShowAutoFillSettingBadgeFlow(userId = activeUserId),
),
) {
FirstTimeState(
showImportLoginsCard = it[0],
showSetupUnlockCard = it[1],
showSetupAutofillCard = it[2],
)
}
}
.onStart {
emit(
FirstTimeState(
showImportLoginsCard = null,
showSetupUnlockCard = null,
showSetupAutofillCard = null,
),
)
}
.distinctUntilChanged()
/**
* Internal implementation to get a flow of the showImportLogins value which takes
* into account if the vault is empty.
*/
private fun getShowImportLoginsFlowInternal(userId: String): Flow<Boolean> {
return authDiskSource.getShowImportLoginsFlow(userId)
.combine(
vaultDiskSource.getCiphers(userId),
) { showImportLogins, ciphers ->
showImportLogins ?: true && ciphers.isEmpty()
}
}
/**
* Get the current [FirstTimeState] of the active user if available, otherwise return
* a default configuration.
*/
override val currentOrDefaultUserFirstTimeState: FirstTimeState
get() =
authDiskSource
.userState
?.activeUserId
?.let {
FirstTimeState(
showImportLoginsCard = authDiskSource.getShowImportLogins(it),
showSetupUnlockCard = settingsDiskSource.getShowUnlockSettingBadge(it),
showSetupAutofillCard = settingsDiskSource.getShowAutoFillSettingBadge(it),
)
}
?: FirstTimeState(
showImportLoginsCard = null,
showSetupUnlockCard = null,
showSetupAutofillCard = null,
)
}

View file

@ -24,6 +24,8 @@ import com.x8bit.bitwarden.data.platform.manager.CrashLogsManagerImpl
import com.x8bit.bitwarden.data.platform.manager.DebugMenuFeatureFlagManagerImpl import com.x8bit.bitwarden.data.platform.manager.DebugMenuFeatureFlagManagerImpl
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManagerImpl import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManagerImpl
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManagerImpl
import com.x8bit.bitwarden.data.platform.manager.NetworkConfigManager import com.x8bit.bitwarden.data.platform.manager.NetworkConfigManager
import com.x8bit.bitwarden.data.platform.manager.NetworkConfigManagerImpl import com.x8bit.bitwarden.data.platform.manager.NetworkConfigManagerImpl
import com.x8bit.bitwarden.data.platform.manager.NetworkConnectionManager import com.x8bit.bitwarden.data.platform.manager.NetworkConnectionManager
@ -55,6 +57,7 @@ import com.x8bit.bitwarden.data.platform.repository.DebugMenuRepository
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
import com.x8bit.bitwarden.data.platform.repository.ServerConfigRepository import com.x8bit.bitwarden.data.platform.repository.ServerConfigRepository
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.vault.datasource.disk.VaultDiskSource
import com.x8bit.bitwarden.data.vault.repository.VaultRepository import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
@ -273,4 +276,20 @@ object PlatformManagerModule {
fun provideResourceCacheManager( fun provideResourceCacheManager(
@ApplicationContext context: Context, @ApplicationContext context: Context,
): ResourceCacheManager = ResourceCacheManagerImpl(context = context) ): ResourceCacheManager = ResourceCacheManagerImpl(context = context)
@Provides
@Singleton
fun provideFirstTimeActionManager(
authDiskSource: AuthDiskSource,
settingsDiskSource: SettingsDiskSource,
vaultDiskSource: VaultDiskSource,
dispatcherManager: DispatcherManager,
featureFlagManager: FeatureFlagManager,
): FirstTimeActionManager = FirstTimeActionManagerImpl(
authDiskSource = authDiskSource,
settingsDiskSource = settingsDiskSource,
vaultDiskSource = vaultDiskSource,
dispatcherManager = dispatcherManager,
featureFlagManager = featureFlagManager,
)
} }

View file

@ -0,0 +1,24 @@
package com.x8bit.bitwarden.data.platform.manager.model
/**
* Model to encapsulate different states for a user's first time experience.
*/
data class FirstTimeState(
val showImportLoginsCard: Boolean,
val showSetupUnlockCard: Boolean,
val showSetupAutofillCard: Boolean,
) {
/**
* Constructs a [FirstTimeState] accepting nullable values. If a value is null, the default
* is used.
*/
constructor(
showImportLoginsCard: Boolean? = null,
showSetupUnlockCard: Boolean? = null,
showSetupAutofillCard: Boolean? = null,
) : this(
showImportLoginsCard = showImportLoginsCard ?: true,
showSetupUnlockCard = showSetupUnlockCard ?: false,
showSetupAutofillCard = showSetupAutofillCard ?: false,
)
}

View file

@ -160,24 +160,6 @@ interface SettingsRepository {
*/ */
val isScreenCaptureAllowedStateFlow: StateFlow<Boolean> val isScreenCaptureAllowedStateFlow: StateFlow<Boolean>
/**
* Returns an observable count of the number of settings items that have a badge to display
* for the current active user.
*/
val allSettingsBadgeCountFlow: StateFlow<Int>
/**
* Returns an observable count of the number of security settings items that have a badge to
* display for the current active user.
*/
val allSecuritySettingsBadgeCountFlow: StateFlow<Int>
/**
* Returns an observable count of the number of autofill settings items that have a badge to
* display for the current active user.
*/
val allAutofillSettingsBadgeCountFlow: StateFlow<Int>
/** /**
* Disables autofill if it is currently enabled. * Disables autofill if it is currently enabled.
*/ */

View file

@ -6,7 +6,6 @@ import com.x8bit.bitwarden.BuildConfig
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation
import com.x8bit.bitwarden.data.auth.repository.model.UserFingerprintResult import com.x8bit.bitwarden.data.auth.repository.model.UserFingerprintResult
import com.x8bit.bitwarden.data.auth.repository.util.activeUserIdChangesFlow
import com.x8bit.bitwarden.data.auth.repository.util.policyInformation import com.x8bit.bitwarden.data.auth.repository.util.policyInformation
import com.x8bit.bitwarden.data.autofill.accessibility.manager.AccessibilityEnabledManager import com.x8bit.bitwarden.data.autofill.accessibility.manager.AccessibilityEnabledManager
import com.x8bit.bitwarden.data.autofill.manager.AutofillEnabledManager import com.x8bit.bitwarden.data.autofill.manager.AutofillEnabledManager
@ -30,8 +29,6 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
@ -340,60 +337,6 @@ class SettingsRepositoryImpl(
?: DEFAULT_IS_SCREEN_CAPTURE_ALLOWED, ?: DEFAULT_IS_SCREEN_CAPTURE_ALLOWED,
) )
override val allSettingsBadgeCountFlow: StateFlow<Int>
get() = combine(
allSecuritySettingsBadgeCountFlow,
allAutofillSettingsBadgeCountFlow,
transform = ::sumSettingsBadgeCount,
)
.stateIn(
scope = unconfinedScope,
started = SharingStarted.Lazily,
initialValue = 0,
)
@OptIn(ExperimentalCoroutinesApi::class)
override val allSecuritySettingsBadgeCountFlow: StateFlow<Int>
get() = authDiskSource
.activeUserIdChangesFlow
.filterNotNull()
.flatMapLatest {
// can be expanded to support multiple security settings
getShowUnlockBadgeFlow(userId = it)
.map { showUnlockBadge ->
listOf(showUnlockBadge)
}
.map { list ->
list.count { badgeOnValue -> badgeOnValue }
}
}
.stateIn(
scope = unconfinedScope,
started = SharingStarted.Lazily,
initialValue = 0,
)
@OptIn(ExperimentalCoroutinesApi::class)
override val allAutofillSettingsBadgeCountFlow: StateFlow<Int>
get() = authDiskSource
.activeUserIdChangesFlow
.filterNotNull()
.flatMapLatest {
// Can be expanded to support multiple autofill settings
getShowAutofillBadgeFlow(userId = it)
.map { showAutofillBadge ->
listOf(showAutofillBadge)
}
.map { list ->
list.count { showBadge -> showBadge }
}
}
.stateIn(
scope = unconfinedScope,
started = SharingStarted.Lazily,
initialValue = 0,
)
init { init {
policyManager policyManager
.getActivePoliciesFlow(type = PolicyTypeJson.MAXIMUM_VAULT_TIMEOUT) .getActivePoliciesFlow(type = PolicyTypeJson.MAXIMUM_VAULT_TIMEOUT)
@ -660,10 +603,6 @@ class SettingsRepositoryImpl(
} }
} }
} }
// helper function to sum badge counts from different settings sub-menus.
private fun sumSettingsBadgeCount(autoFillBadgeCount: Int, securityBadgeCount: Int) =
autoFillBadgeCount + securityBadgeCount
} }
/** /**

View file

@ -3,9 +3,9 @@ package com.x8bit.bitwarden.ui.platform.feature.settings
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.BackgroundEvent import com.x8bit.bitwarden.ui.platform.base.util.BackgroundEvent
import com.x8bit.bitwarden.ui.platform.base.util.Text import com.x8bit.bitwarden.ui.platform.base.util.Text
@ -22,19 +22,19 @@ import javax.inject.Inject
*/ */
@HiltViewModel @HiltViewModel
class SettingsViewModel @Inject constructor( class SettingsViewModel @Inject constructor(
settingsRepository: SettingsRepository,
specialCircumstanceManager: SpecialCircumstanceManager, specialCircumstanceManager: SpecialCircumstanceManager,
firstTimeActionManager: FirstTimeActionManager,
) : BaseViewModel<SettingsState, SettingsEvent, SettingsAction>( ) : BaseViewModel<SettingsState, SettingsEvent, SettingsAction>(
initialState = SettingsState( initialState = SettingsState(
securityCount = settingsRepository.allSecuritySettingsBadgeCountFlow.value, securityCount = firstTimeActionManager.allSecuritySettingsBadgeCountFlow.value,
autoFillCount = settingsRepository.allAutofillSettingsBadgeCountFlow.value, autoFillCount = firstTimeActionManager.allAutofillSettingsBadgeCountFlow.value,
), ),
) { ) {
init { init {
combine( combine(
settingsRepository.allSecuritySettingsBadgeCountFlow, firstTimeActionManager.allSecuritySettingsBadgeCountFlow,
settingsRepository.allAutofillSettingsBadgeCountFlow, firstTimeActionManager.allAutofillSettingsBadgeCountFlow,
) { securityCount, autofillCount -> ) { securityCount, autofillCount ->
SettingsAction.Internal.SettingsNotificationCountUpdate( SettingsAction.Internal.SettingsNotificationCountUpdate(
securityCount = securityCount, securityCount = securityCount,

View file

@ -5,9 +5,9 @@ import androidx.lifecycle.viewModelScope
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.BackgroundEvent import com.x8bit.bitwarden.ui.platform.base.util.BackgroundEvent
import com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar.model.VaultUnlockedNavBarTab import com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar.model.VaultUnlockedNavBarTab
@ -24,13 +24,13 @@ import javax.inject.Inject
class VaultUnlockedNavBarViewModel @Inject constructor( class VaultUnlockedNavBarViewModel @Inject constructor(
authRepository: AuthRepository, authRepository: AuthRepository,
specialCircumstancesManager: SpecialCircumstanceManager, specialCircumstancesManager: SpecialCircumstanceManager,
settingsRepository: SettingsRepository, firstTimeActionManager: FirstTimeActionManager,
) : BaseViewModel<VaultUnlockedNavBarState, VaultUnlockedNavBarEvent, VaultUnlockedNavBarAction>( ) : BaseViewModel<VaultUnlockedNavBarState, VaultUnlockedNavBarEvent, VaultUnlockedNavBarAction>(
initialState = VaultUnlockedNavBarState( initialState = VaultUnlockedNavBarState(
vaultNavBarLabelRes = R.string.my_vault, vaultNavBarLabelRes = R.string.my_vault,
vaultNavBarContentDescriptionRes = R.string.my_vault, vaultNavBarContentDescriptionRes = R.string.my_vault,
notificationState = VaultUnlockedNavBarNotificationState( notificationState = VaultUnlockedNavBarNotificationState(
settingsTabNotificationCount = settingsRepository.allSettingsBadgeCountFlow.value, settingsTabNotificationCount = firstTimeActionManager.allSettingsBadgeCountFlow.value,
), ),
), ),
) { ) {
@ -42,7 +42,7 @@ class VaultUnlockedNavBarViewModel @Inject constructor(
} }
.launchIn(viewModelScope) .launchIn(viewModelScope)
settingsRepository firstTimeActionManager
.allSettingsBadgeCountFlow .allSettingsBadgeCountFlow
.onEach { .onEach {
sendAction(VaultUnlockedNavBarAction.Internal.SettingsNotificationCountUpdate(it)) sendAction(VaultUnlockedNavBarAction.Internal.SettingsNotificationCountUpdate(it))

View file

@ -8,6 +8,7 @@ import com.bitwarden.vault.CipherView
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.EmailTokenResult import com.x8bit.bitwarden.data.auth.repository.model.EmailTokenResult
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.util.getCompleteRegistrationDataIntentOrNull import com.x8bit.bitwarden.data.auth.util.getCompleteRegistrationDataIntentOrNull
@ -1156,7 +1157,7 @@ private val DEFAULT_STATE: MainState = MainState(
isScreenCaptureAllowed = true, isScreenCaptureAllowed = true,
) )
private val DEFAULT_FIRST_TIME_STATE = UserState.FirstTimeState( private val DEFAULT_FIRST_TIME_STATE = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
) )

View file

@ -65,6 +65,7 @@ import com.x8bit.bitwarden.data.auth.repository.model.AuthState
import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult
import com.x8bit.bitwarden.data.auth.repository.model.DeleteAccountResult import com.x8bit.bitwarden.data.auth.repository.model.DeleteAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.EmailTokenResult import com.x8bit.bitwarden.data.auth.repository.model.EmailTokenResult
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.KnownDeviceResult import com.x8bit.bitwarden.data.auth.repository.model.KnownDeviceResult
import com.x8bit.bitwarden.data.auth.repository.model.LoginResult import com.x8bit.bitwarden.data.auth.repository.model.LoginResult
import com.x8bit.bitwarden.data.auth.repository.model.NewSsoUserResult import com.x8bit.bitwarden.data.auth.repository.model.NewSsoUserResult
@ -82,7 +83,6 @@ import com.x8bit.bitwarden.data.auth.repository.model.SetPasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePinResult import com.x8bit.bitwarden.data.auth.repository.model.ValidatePinResult
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
@ -102,6 +102,7 @@ import com.x8bit.bitwarden.data.platform.datasource.disk.model.ServerConfig
import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeConfigDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeConfigDiskSource
import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.PolicyManager import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.PushManager import com.x8bit.bitwarden.data.platform.manager.PushManager
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
@ -244,6 +245,11 @@ class AuthRepositoryTest {
every { getFeatureFlag(FlagKey.OnboardingFlow) } returns false every { getFeatureFlag(FlagKey.OnboardingFlow) } returns false
} }
private val firstTimeActionManager = mockk<FirstTimeActionManager> {
every { currentOrDefaultUserFirstTimeState } returns FIRST_TIME_STATE
every { firstTimeStateFlow } returns MutableStateFlow(FIRST_TIME_STATE)
}
private val repository = AuthRepositoryImpl( private val repository = AuthRepositoryImpl(
accountsService = accountsService, accountsService = accountsService,
devicesService = devicesService, devicesService = devicesService,
@ -265,6 +271,7 @@ class AuthRepositoryTest {
pushManager = pushManager, pushManager = pushManager,
policyManager = policyManager, policyManager = policyManager,
featureFlagManager = featureFlagManager, featureFlagManager = featureFlagManager,
firstTimeActionManager = firstTimeActionManager,
) )
@BeforeEach @BeforeEach
@ -6544,7 +6551,7 @@ class AuthRepositoryTest {
), ),
) )
private val FIRST_TIME_STATE = UserState.FirstTimeState( private val FIRST_TIME_STATE = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
) )

View file

@ -11,7 +11,6 @@ import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.UserSwitchingData import com.x8bit.bitwarden.data.auth.repository.model.UserSwitchingData
import com.x8bit.bitwarden.data.vault.datasource.network.model.OrganizationType import com.x8bit.bitwarden.data.vault.datasource.network.model.OrganizationType
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockOrganization import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockOrganization
@ -507,48 +506,6 @@ class AuthDiskSourceExtensionsTest {
authDiskSource.currentOnboardingStatus, authDiskSource.currentOnboardingStatus,
) )
} }
@Test
fun `firstTimeStateFlow should emit changes when items in the first time state change`() =
runTest {
authDiskSource.firstTimeStateFlow.test {
authDiskSource.userState = MOCK_USER_STATE
assertEquals(
UserState.FirstTimeState(
showImportLoginsCard = true,
),
awaitItem(),
)
authDiskSource.storeShowImportLogins(MOCK_USER_ID, false)
assertEquals(
UserState.FirstTimeState(
showImportLoginsCard = false,
),
awaitItem(),
)
}
}
@Suppress("MaxLineLength")
@Test
fun `currentOrDefaultUserFirstTimeState should return the current first time state or a default state`() {
authDiskSource.userState = MOCK_USER_STATE
// Assert default state when no values set
assertEquals(
UserState.FirstTimeState(
showImportLoginsCard = true,
),
authDiskSource.currentOrDefaultUserFirstTimeState,
)
authDiskSource.storeShowImportLogins(MOCK_USER_ID, false)
assertEquals(
UserState.FirstTimeState(
showImportLoginsCard = false,
),
authDiskSource.currentOrDefaultUserFirstTimeState,
)
}
} }
private const val MOCK_USER_ID: String = "mockId-1" private const val MOCK_USER_ID: String = "mockId-1"

View file

@ -10,6 +10,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.KdfTypeJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorUserDecryptionOptionsJson import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorUserDecryptionOptionsJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceUserDecryptionOptionsJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceUserDecryptionOptionsJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.UserDecryptionOptionsJson import com.x8bit.bitwarden.data.auth.datasource.network.model.UserDecryptionOptionsJson
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens import com.x8bit.bitwarden.data.auth.repository.model.UserAccountTokens
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
@ -358,7 +359,7 @@ class UserStateJsonExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.NOT_STARTED, onboardingStatus = OnboardingStatus.NOT_STARTED,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
), ),
@ -428,7 +429,7 @@ class UserStateJsonExtensionsTest {
vaultUnlockTypeProvider = { VaultUnlockType.PIN }, vaultUnlockTypeProvider = { VaultUnlockType.PIN },
isDeviceTrustedProvider = { false }, isDeviceTrustedProvider = { false },
onboardingStatus = OnboardingStatus.NOT_STARTED, onboardingStatus = OnboardingStatus.NOT_STARTED,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
) )
} }
@ -466,7 +467,7 @@ class UserStateJsonExtensionsTest {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.NOT_STARTED, onboardingStatus = OnboardingStatus.NOT_STARTED,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
hasPendingAccountAddition = true, hasPendingAccountAddition = true,
@ -532,7 +533,7 @@ class UserStateJsonExtensionsTest {
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD }, vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
isDeviceTrustedProvider = { false }, isDeviceTrustedProvider = { false },
onboardingStatus = OnboardingStatus.NOT_STARTED, onboardingStatus = OnboardingStatus.NOT_STARTED,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
) )
} }
@ -576,7 +577,7 @@ class UserStateJsonExtensionsTest {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = true, isUsingKeyConnector = true,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
hasPendingAccountAddition = true, hasPendingAccountAddition = true,
@ -645,7 +646,7 @@ class UserStateJsonExtensionsTest {
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD }, vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
isDeviceTrustedProvider = { true }, isDeviceTrustedProvider = { true },
onboardingStatus = null, onboardingStatus = null,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
) )
} }
@ -689,7 +690,7 @@ class UserStateJsonExtensionsTest {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = true, isUsingKeyConnector = true,
onboardingStatus = OnboardingStatus.AUTOFILL_SETUP, onboardingStatus = OnboardingStatus.AUTOFILL_SETUP,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
hasPendingAccountAddition = true, hasPendingAccountAddition = true,
@ -758,7 +759,7 @@ class UserStateJsonExtensionsTest {
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD }, vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
isDeviceTrustedProvider = { true }, isDeviceTrustedProvider = { true },
onboardingStatus = OnboardingStatus.AUTOFILL_SETUP, onboardingStatus = OnboardingStatus.AUTOFILL_SETUP,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
) )
} }
@ -802,7 +803,7 @@ class UserStateJsonExtensionsTest {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = true, isUsingKeyConnector = true,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
hasPendingAccountAddition = true, hasPendingAccountAddition = true,
@ -871,7 +872,7 @@ class UserStateJsonExtensionsTest {
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD }, vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
isDeviceTrustedProvider = { true }, isDeviceTrustedProvider = { true },
onboardingStatus = null, onboardingStatus = null,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
) )
} }
@ -919,7 +920,7 @@ class UserStateJsonExtensionsTest {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = true, isUsingKeyConnector = true,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
hasPendingAccountAddition = true, hasPendingAccountAddition = true,
@ -988,7 +989,7 @@ class UserStateJsonExtensionsTest {
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD }, vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
isDeviceTrustedProvider = { true }, isDeviceTrustedProvider = { true },
onboardingStatus = null, onboardingStatus = null,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
) )
} }
@ -1017,7 +1018,7 @@ class UserStateJsonExtensionsTest {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
hasPendingAccountAddition = true, hasPendingAccountAddition = true,
@ -1066,7 +1067,7 @@ class UserStateJsonExtensionsTest {
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD }, vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
isDeviceTrustedProvider = { true }, isDeviceTrustedProvider = { true },
onboardingStatus = null, onboardingStatus = null,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
) )
} }
@ -1095,7 +1096,7 @@ class UserStateJsonExtensionsTest {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = true, isUsingKeyConnector = true,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
hasPendingAccountAddition = true, hasPendingAccountAddition = true,
@ -1146,7 +1147,7 @@ class UserStateJsonExtensionsTest {
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD }, vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
isDeviceTrustedProvider = { true }, isDeviceTrustedProvider = { true },
onboardingStatus = null, onboardingStatus = null,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
) )
} }
@ -1191,7 +1192,7 @@ class UserStateJsonExtensionsTest {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = true, isUsingKeyConnector = true,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
hasPendingAccountAddition = true, hasPendingAccountAddition = true,
@ -1262,7 +1263,7 @@ class UserStateJsonExtensionsTest {
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD }, vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
isDeviceTrustedProvider = { true }, isDeviceTrustedProvider = { true },
onboardingStatus = null, onboardingStatus = null,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
) )
} }
@ -1306,7 +1307,7 @@ class UserStateJsonExtensionsTest {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = true, isUsingKeyConnector = true,
onboardingStatus = OnboardingStatus.AUTOFILL_SETUP, onboardingStatus = OnboardingStatus.AUTOFILL_SETUP,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = false, showImportLoginsCard = false,
), ),
), ),
@ -1377,7 +1378,7 @@ class UserStateJsonExtensionsTest {
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD }, vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
isDeviceTrustedProvider = { true }, isDeviceTrustedProvider = { true },
onboardingStatus = OnboardingStatus.AUTOFILL_SETUP, onboardingStatus = OnboardingStatus.AUTOFILL_SETUP,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = false, showImportLoginsCard = false,
), ),
), ),

View file

@ -24,6 +24,7 @@ import com.bitwarden.sdk.Fido2CredentialStore
import com.bitwarden.vault.CipherView import com.bitwarden.vault.CipherView
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
import com.x8bit.bitwarden.data.autofill.fido2.manager.Fido2CredentialManager import com.x8bit.bitwarden.data.autofill.fido2.manager.Fido2CredentialManager
@ -537,7 +538,7 @@ private fun createMockAccounts(number: Int): List<UserState.Account> {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
) )
} }

View file

@ -0,0 +1,234 @@
package com.x8bit.bitwarden.data.platform.manager
import app.cash.turbine.test
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
import com.x8bit.bitwarden.data.auth.datasource.network.model.KdfTypeJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceUserDecryptionOptionsJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.UserDecryptionOptionsJson
import com.x8bit.bitwarden.data.platform.base.FakeDispatcherManager
import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeSettingsDiskSource
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 com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class FirstTimeActionManagerTest {
private val fakeAuthDiskSource = FakeAuthDiskSource()
private val fakeSettingsDiskSource = FakeSettingsDiskSource()
private val mutableCiphersListFlow = MutableStateFlow(emptyList<SyncResponseJson.Cipher>())
private val vaultDiskSource = mockk<VaultDiskSource> {
every { getCiphers(any()) } returns mutableCiphersListFlow
}
private val mutableImportLoginsFlow = MutableStateFlow(false)
private val featureFlagManager = mockk<FeatureFlagManager> {
every { getFeatureFlagFlow(FlagKey.ImportLoginsFlow) } returns mutableImportLoginsFlow
}
private val firstTimeActionManager = FirstTimeActionManagerImpl(
authDiskSource = fakeAuthDiskSource,
settingsDiskSource = fakeSettingsDiskSource,
vaultDiskSource = vaultDiskSource,
featureFlagManager = featureFlagManager,
dispatcherManager = FakeDispatcherManager(),
)
@Suppress("MaxLineLength")
@Test
fun `allAutoFillSettingsBadgeCountFlow should emit the value of flags set to true and update when changed`() =
runTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
firstTimeActionManager.allAutofillSettingsBadgeCountFlow.test {
assertEquals(0, awaitItem())
fakeSettingsDiskSource.storeShowAutoFillSettingBadge(
userId = USER_ID,
showBadge = true,
)
assertEquals(1, awaitItem())
fakeSettingsDiskSource.storeShowAutoFillSettingBadge(
userId = USER_ID,
showBadge = false,
)
assertEquals(0, awaitItem())
}
}
@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())
}
}
@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 }
fakeAuthDiskSource.storeShowImportLogins(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`() =
runTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
val mockCipher = mockk<SyncResponseJson.Cipher>(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.
firstTimeActionManager.allVaultSettingsBadgeCountFlow.test {
assertEquals(0, awaitItem())
mutableImportLoginsFlow.update { true }
fakeAuthDiskSource.storeShowImportLogins(USER_ID, true)
assertEquals(1, awaitItem())
mutableImportLoginsFlow.update { false }
assertEquals(0, awaitItem())
mutableImportLoginsFlow.update { true }
assertEquals(1, awaitItem())
fakeAuthDiskSource.storeShowImportLogins(USER_ID, false)
assertEquals(0, awaitItem())
fakeAuthDiskSource.storeShowImportLogins(USER_ID, true)
assertEquals(1, awaitItem())
mutableCiphersListFlow.update {
listOf(mockCipher)
}
assertEquals(0, awaitItem())
}
}
@Test
fun `firstTimeStateFlow should emit changes when items in the first time state change`() =
runTest {
firstTimeActionManager.firstTimeStateFlow.test {
fakeAuthDiskSource.userState =
MOCK_USER_STATE
assertEquals(
FirstTimeState(
showImportLoginsCard = true,
),
awaitItem(),
)
fakeAuthDiskSource.storeShowImportLogins(USER_ID, false)
assertEquals(
FirstTimeState(
showImportLoginsCard = false,
),
awaitItem(),
)
}
}
@Suppress("MaxLineLength")
@Test
fun `currentOrDefaultUserFirstTimeState should return the current first time state or a default state`() {
fakeAuthDiskSource.userState = MOCK_USER_STATE
// Assert default state when no values set
assertEquals(
FirstTimeState(
showImportLoginsCard = true,
),
firstTimeActionManager.currentOrDefaultUserFirstTimeState,
)
fakeAuthDiskSource.storeShowImportLogins(USER_ID, false)
assertEquals(
FirstTimeState(
showImportLoginsCard = false,
),
firstTimeActionManager.currentOrDefaultUserFirstTimeState,
)
}
}
private const val USER_ID: String = "userId"
private val MOCK_TRUSTED_DEVICE_USER_DECRYPTION_OPTIONS = TrustedDeviceUserDecryptionOptionsJson(
encryptedPrivateKey = null,
encryptedUserKey = null,
hasAdminApproval = false,
hasLoginApprovingDevice = false,
hasManageResetPasswordPermission = false,
)
private val MOCK_USER_DECRYPTION_OPTIONS: UserDecryptionOptionsJson = UserDecryptionOptionsJson(
hasMasterPassword = false,
trustedDeviceUserDecryptionOptions = MOCK_TRUSTED_DEVICE_USER_DECRYPTION_OPTIONS,
keyConnectorUserDecryptionOptions = null,
)
private val MOCK_PROFILE = AccountJson.Profile(
userId = USER_ID,
email = "test@bitwarden.com",
isEmailVerified = true,
name = "Bitwarden Tester",
hasPremium = false,
stamp = null,
organizationId = null,
avatarColorHex = null,
forcePasswordResetReason = null,
kdfType = KdfTypeJson.ARGON2_ID,
kdfIterations = 600000,
kdfMemory = 16,
kdfParallelism = 4,
userDecryptionOptions = MOCK_USER_DECRYPTION_OPTIONS,
)
private val MOCK_ACCOUNT = AccountJson(
profile = MOCK_PROFILE,
settings = AccountJson.Settings(
environmentUrlData = EnvironmentUrlDataJson.DEFAULT_US,
),
)
private val MOCK_USER_STATE = UserStateJson(
activeUserId = USER_ID,
accounts = mapOf(
USER_ID to MOCK_ACCOUNT,
),
)

View file

@ -1234,71 +1234,6 @@ class SettingsRepositoryTest {
assertTrue(awaitItem()) assertTrue(awaitItem())
} }
} }
@Suppress("MaxLineLength")
@Test
fun `allAutoFillSettingsBadgeCountFlow should emit the value of flags set to true and update when changed`() =
runTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
settingsRepository.allAutofillSettingsBadgeCountFlow.test {
assertEquals(0, awaitItem())
fakeSettingsDiskSource.storeShowAutoFillSettingBadge(
userId = USER_ID,
showBadge = true,
)
assertEquals(1, awaitItem())
fakeSettingsDiskSource.storeShowAutoFillSettingBadge(
userId = USER_ID,
showBadge = false,
)
assertEquals(0, awaitItem())
}
}
@Suppress("MaxLineLength")
@Test
fun `allSecuritySettingsBadgeCountFlow should emit the value of flags set to true and update when changed`() =
runTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
settingsRepository.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
settingsRepository.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())
}
}
} }
private const val USER_ID: String = "userId" private const val USER_ID: String = "userId"

View file

@ -5,6 +5,7 @@ import app.cash.turbine.test
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
@ -388,7 +389,7 @@ private val DEFAULT_USER_ACCOUNT = UserState.Account(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.ACCOUNT_LOCK_SETUP, onboardingStatus = OnboardingStatus.ACCOUNT_LOCK_SETUP,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
private val CIPHER = mockk<Cipher>() private val CIPHER = mockk<Cipher>()

View file

@ -5,6 +5,7 @@ import app.cash.turbine.test
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
@ -88,7 +89,7 @@ class LandingViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )
@ -226,7 +227,7 @@ class LandingViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
val userState = UserState( val userState = UserState(
activeUserId = "activeUserId", activeUserId = "activeUserId",
@ -283,7 +284,7 @@ class LandingViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
val userState = UserState( val userState = UserState(
activeUserId = "activeUserId", activeUserId = "activeUserId",
@ -344,7 +345,7 @@ class LandingViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
val userState = UserState( val userState = UserState(
activeUserId = "activeUserId", activeUserId = "activeUserId",
@ -521,7 +522,7 @@ class LandingViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
val userState = UserState( val userState = UserState(
@ -557,7 +558,7 @@ class LandingViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
val userState = UserState( val userState = UserState(

View file

@ -7,6 +7,7 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.KnownDeviceResult import com.x8bit.bitwarden.data.auth.repository.model.KnownDeviceResult
import com.x8bit.bitwarden.data.auth.repository.model.LoginResult import com.x8bit.bitwarden.data.auth.repository.model.LoginResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
@ -131,7 +132,7 @@ class LoginViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -5,6 +5,7 @@ import app.cash.turbine.test
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.RemovePasswordResult import com.x8bit.bitwarden.data.auth.repository.model.RemovePasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
@ -167,7 +168,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
private val DEFAULT_USER_STATE = UserState( private val DEFAULT_USER_STATE = UserState(

View file

@ -6,6 +6,7 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.AuthState import com.x8bit.bitwarden.data.auth.repository.model.AuthState
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.NewSsoUserResult import com.x8bit.bitwarden.data.auth.repository.model.NewSsoUserResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
@ -276,7 +277,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
private val DEFAULT_USER_STATE = UserState( private val DEFAULT_USER_STATE = UserState(

View file

@ -6,6 +6,7 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
@ -219,7 +220,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )
@ -259,7 +260,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
@ -1134,7 +1135,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
private val DEFAULT_USER_STATE = UserState( private val DEFAULT_USER_STATE = UserState(

View file

@ -4,6 +4,7 @@ import android.content.pm.SigningInfo
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.AuthState import com.x8bit.bitwarden.data.auth.repository.model.AuthState
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.JwtTokenDataJson import com.x8bit.bitwarden.data.auth.repository.model.JwtTokenDataJson
import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
@ -106,7 +107,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -143,7 +144,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -177,7 +178,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -221,7 +222,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -262,7 +263,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -303,7 +304,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = false, hasMasterPassword = false,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -341,7 +342,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -392,7 +393,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -427,7 +428,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -467,7 +468,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -506,7 +507,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
trustedDevice = null, trustedDevice = null,
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
firstTimeState = UserState.FirstTimeState(false), firstTimeState = FirstTimeState(false),
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
), ),
), ),
@ -548,7 +549,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -591,7 +592,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -641,7 +642,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -691,7 +692,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -736,7 +737,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -780,7 +781,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -859,7 +860,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -913,7 +914,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -975,7 +976,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -1017,7 +1018,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -1054,7 +1055,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -1089,7 +1090,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.NOT_STARTED, onboardingStatus = OnboardingStatus.NOT_STARTED,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -1127,7 +1128,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.ACCOUNT_LOCK_SETUP, onboardingStatus = OnboardingStatus.ACCOUNT_LOCK_SETUP,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -1165,7 +1166,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.AUTOFILL_SETUP, onboardingStatus = OnboardingStatus.AUTOFILL_SETUP,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -1203,7 +1204,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.FINAL_STEP, onboardingStatus = OnboardingStatus.FINAL_STEP,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -1241,7 +1242,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.NOT_STARTED, onboardingStatus = OnboardingStatus.NOT_STARTED,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -1279,7 +1280,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),
@ -1317,7 +1318,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState( firstTimeState = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
), ),
), ),

View file

@ -9,6 +9,7 @@ import com.bitwarden.vault.LoginUriView
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.autofill.accessibility.manager.AccessibilitySelectionManager import com.x8bit.bitwarden.data.autofill.accessibility.manager.AccessibilitySelectionManager
@ -1537,7 +1538,7 @@ private val DEFAULT_USER_STATE = UserState(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -1,9 +1,9 @@
package com.x8bit.bitwarden.ui.platform.feature.settings package com.x8bit.bitwarden.ui.platform.feature.settings
import app.cash.turbine.test import app.cash.turbine.test
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
import io.mockk.every import io.mockk.every
import io.mockk.just import io.mockk.just
@ -20,7 +20,7 @@ class SettingsViewModelTest : BaseViewModelTest() {
private val mutableAutofillBadgeCountFlow = MutableStateFlow(0) private val mutableAutofillBadgeCountFlow = MutableStateFlow(0)
private val mutableSecurityBadgeCountFlow = MutableStateFlow(0) private val mutableSecurityBadgeCountFlow = MutableStateFlow(0)
private val settingsRepository = mockk<SettingsRepository> { private val firstTimeManager = mockk<FirstTimeActionManager> {
every { allSecuritySettingsBadgeCountFlow } returns mutableSecurityBadgeCountFlow every { allSecuritySettingsBadgeCountFlow } returns mutableSecurityBadgeCountFlow
every { allAutofillSettingsBadgeCountFlow } returns mutableAutofillBadgeCountFlow every { allAutofillSettingsBadgeCountFlow } returns mutableAutofillBadgeCountFlow
} }
@ -145,7 +145,7 @@ class SettingsViewModelTest : BaseViewModelTest() {
} }
private fun createViewModel() = SettingsViewModel( private fun createViewModel() = SettingsViewModel(
settingsRepository = settingsRepository, firstTimeActionManager = firstTimeManager,
specialCircumstanceManager = specialCircumstanceManager, specialCircumstanceManager = specialCircumstanceManager,
) )
} }

View file

@ -5,6 +5,7 @@ import app.cash.turbine.test
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation
import com.x8bit.bitwarden.data.auth.repository.model.UserFingerprintResult import com.x8bit.bitwarden.data.auth.repository.model.UserFingerprintResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
@ -792,7 +793,7 @@ private val DEFAULT_USER_STATE = UserState(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -6,6 +6,7 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.DeleteAccountResult import com.x8bit.bitwarden.data.auth.repository.model.DeleteAccountResult
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.platform.repository.model.Environment import com.x8bit.bitwarden.data.platform.repository.model.Environment
@ -244,7 +245,7 @@ private val DEFAULT_USER_STATE: UserState = UserState(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -8,6 +8,7 @@ import com.x8bit.bitwarden.data.auth.manager.model.AuthRequest
import com.x8bit.bitwarden.data.auth.manager.model.AuthRequestResult import com.x8bit.bitwarden.data.auth.manager.model.AuthRequestResult
import com.x8bit.bitwarden.data.auth.manager.model.AuthRequestUpdatesResult import com.x8bit.bitwarden.data.auth.manager.model.AuthRequestUpdatesResult
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.model.PasswordlessRequestData import com.x8bit.bitwarden.data.platform.manager.model.PasswordlessRequestData
@ -372,7 +373,7 @@ private val DEFAULT_USER_STATE = UserState(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -8,6 +8,7 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.datasource.sdk.model.PasswordStrength import com.x8bit.bitwarden.data.auth.datasource.sdk.model.PasswordStrength
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.PasswordStrengthResult import com.x8bit.bitwarden.data.auth.repository.model.PasswordStrengthResult
import com.x8bit.bitwarden.data.auth.repository.model.RequestOtpResult import com.x8bit.bitwarden.data.auth.repository.model.RequestOtpResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
@ -724,7 +725,7 @@ private val DEFAULT_USER_STATE = UserState(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -4,9 +4,9 @@ import app.cash.turbine.test
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.manager.FirstTimeActionManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
import io.mockk.every import io.mockk.every
import io.mockk.just import io.mockk.just
@ -29,7 +29,7 @@ class VaultUnlockedNavBarViewModelTest : BaseViewModelTest() {
} }
private val mutableSettingsBadgeCountFlow = MutableStateFlow(0) private val mutableSettingsBadgeCountFlow = MutableStateFlow(0)
private val settingsRepository: SettingsRepository = mockk { private val firstTimeActionManager: FirstTimeActionManager = mockk {
every { allSettingsBadgeCountFlow } returns mutableSettingsBadgeCountFlow every { allSettingsBadgeCountFlow } returns mutableSettingsBadgeCountFlow
} }
@ -253,7 +253,7 @@ class VaultUnlockedNavBarViewModelTest : BaseViewModelTest() {
VaultUnlockedNavBarViewModel( VaultUnlockedNavBarViewModel(
authRepository = authRepository, authRepository = authRepository,
specialCircumstancesManager = specialCircumstancesManager, specialCircumstancesManager = specialCircumstancesManager,
settingsRepository = settingsRepository, firstTimeActionManager = firstTimeActionManager,
) )
} }

View file

@ -7,6 +7,7 @@ import com.bitwarden.generators.PasswordGeneratorRequest
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.manager.PolicyManager import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
@ -2408,7 +2409,7 @@ private val DEFAULT_USER_STATE = UserState(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -7,6 +7,7 @@ import com.bitwarden.send.SendView
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.manager.PolicyManager import com.x8bit.bitwarden.data.platform.manager.PolicyManager
@ -1103,7 +1104,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
private val DEFAULT_USER_STATE = UserState( private val DEFAULT_USER_STATE = UserState(

View file

@ -13,6 +13,7 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
@ -3965,7 +3966,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
hasPendingAccountAddition = false, hasPendingAccountAddition = false,

View file

@ -14,6 +14,7 @@ import com.bitwarden.vault.SecureNoteType
import com.bitwarden.vault.SecureNoteView import com.bitwarden.vault.SecureNoteView
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
@ -513,7 +514,7 @@ class CipherViewExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
} }

View file

@ -7,6 +7,7 @@ import com.bitwarden.vault.CipherView
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.repository.model.DataState import com.x8bit.bitwarden.data.platform.repository.model.DataState
import com.x8bit.bitwarden.data.platform.repository.model.Environment import com.x8bit.bitwarden.data.platform.repository.model.Environment
@ -564,7 +565,7 @@ private val DEFAULT_USER_STATE = UserState(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -9,6 +9,7 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
@ -2581,7 +2582,7 @@ class VaultItemViewModelTest : BaseViewModelTest() {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -10,6 +10,7 @@ import com.bitwarden.vault.CipherView
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
@ -4032,7 +4033,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
private val DEFAULT_USER_STATE = UserState( private val DEFAULT_USER_STATE = UserState(

View file

@ -7,6 +7,7 @@ import com.bitwarden.vault.CollectionView
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.repository.model.DataState import com.x8bit.bitwarden.data.platform.repository.model.DataState
@ -515,7 +516,7 @@ private val DEFAULT_USER_STATE = UserState(
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -2,6 +2,7 @@ package com.x8bit.bitwarden.ui.vault.feature.movetoorganization.util
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.repository.model.Environment import com.x8bit.bitwarden.data.platform.repository.model.Environment
@ -130,7 +131,7 @@ private fun createMockUserState(hasOrganizations: Boolean = true): UserState =
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )

View file

@ -4,6 +4,7 @@ import app.cash.turbine.test
import com.x8bit.bitwarden.R import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
@ -1639,7 +1640,7 @@ private val VAULT_FILTER_DATA = VaultFilterData(
private val DEFAULT_STATE: VaultState = private val DEFAULT_STATE: VaultState =
createMockVaultState(viewState = VaultState.ViewState.Loading) createMockVaultState(viewState = VaultState.ViewState.Loading)
private val DEFAULT_FIRST_TIME_STATE = UserState.FirstTimeState( private val DEFAULT_FIRST_TIME_STATE = FirstTimeState(
showImportLoginsCard = true, showImportLoginsCard = true,
) )

View file

@ -2,6 +2,7 @@ package com.x8bit.bitwarden.ui.vault.feature.vault.util
import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.UserState import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.platform.repository.model.Environment import com.x8bit.bitwarden.data.platform.repository.model.Environment
@ -87,7 +88,7 @@ class UserStateExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
UserState.Account( UserState.Account(
userId = "lockedUserId", userId = "lockedUserId",
@ -114,7 +115,7 @@ class UserStateExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
UserState.Account( UserState.Account(
userId = "unlockedUserId", userId = "unlockedUserId",
@ -145,7 +146,7 @@ class UserStateExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
UserState.Account( UserState.Account(
userId = "loggedOutUserId", userId = "loggedOutUserId",
@ -176,7 +177,7 @@ class UserStateExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )
@ -222,7 +223,7 @@ class UserStateExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
.toAccountSummary(isActive = true), .toAccountSummary(isActive = true),
) )
@ -266,7 +267,7 @@ class UserStateExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
.toAccountSummary(isActive = false), .toAccountSummary(isActive = false),
) )
@ -314,7 +315,7 @@ class UserStateExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
), ),
), ),
) )
@ -342,7 +343,7 @@ class UserStateExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
.toVaultFilterData(isIndividualVaultDisabled = false), .toVaultFilterData(isIndividualVaultDisabled = false),
) )
@ -399,7 +400,7 @@ class UserStateExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
.toVaultFilterData( .toVaultFilterData(
isIndividualVaultDisabled = false, isIndividualVaultDisabled = false,
@ -457,7 +458,7 @@ class UserStateExtensionsTest {
hasMasterPassword = true, hasMasterPassword = true,
isUsingKeyConnector = false, isUsingKeyConnector = false,
onboardingStatus = OnboardingStatus.COMPLETE, onboardingStatus = OnboardingStatus.COMPLETE,
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true), firstTimeState = FirstTimeState(showImportLoginsCard = true),
) )
.toVaultFilterData( .toVaultFilterData(
isIndividualVaultDisabled = true, isIndividualVaultDisabled = true,