mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 07:05:35 +03:00
PM-13464 and PM-13627 support (#4107)
This commit is contained in:
parent
5faa30e2f2
commit
56ad1ef05b
45 changed files with 662 additions and 357 deletions
|
@ -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.DeleteAccountResult
|
||||
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.LoginResult
|
||||
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.activeUserIdChangesFlow
|
||||
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.policyInformation
|
||||
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.platform.datasource.disk.ConfigDiskSource
|
||||
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.PushManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||
|
@ -164,6 +164,7 @@ class AuthRepositoryImpl(
|
|||
private val userLogoutManager: UserLogoutManager,
|
||||
private val policyManager: PolicyManager,
|
||||
private val featureFlagManager: FeatureFlagManager,
|
||||
private val firstTimeActionManager: FirstTimeActionManager,
|
||||
pushManager: PushManager,
|
||||
dispatcherManager: DispatcherManager,
|
||||
) : AuthRepository,
|
||||
|
@ -258,7 +259,7 @@ class AuthRepositoryImpl(
|
|||
authDiskSource.userOrganizationsListFlow,
|
||||
authDiskSource.userKeyConnectorStateFlow,
|
||||
authDiskSource.onboardingStatusChangesFlow,
|
||||
authDiskSource.firstTimeStateFlow,
|
||||
firstTimeActionManager.firstTimeStateFlow,
|
||||
vaultRepository.vaultUnlockDataStateFlow,
|
||||
mutableHasPendingAccountAdditionStateFlow,
|
||||
// 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 userIsUsingKeyConnectorList = array[3] as List<UserKeyConnectorState>
|
||||
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 hasPendingAccountAddition = array[7] as Boolean
|
||||
userStateJson?.toUserState(
|
||||
|
@ -305,7 +306,7 @@ class AuthRepositoryImpl(
|
|||
isBiometricsEnabledProvider = ::isBiometricsEnabled,
|
||||
vaultUnlockTypeProvider = ::getVaultUnlockType,
|
||||
isDeviceTrustedProvider = ::isDeviceTrusted,
|
||||
firstTimeState = authDiskSource.currentOrDefaultUserFirstTimeState,
|
||||
firstTimeState = firstTimeActionManager.currentOrDefaultUserFirstTimeState,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -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.platform.datasource.disk.ConfigDiskSource
|
||||
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.PushManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||
|
@ -58,6 +59,7 @@ object AuthRepositoryModule {
|
|||
pushManager: PushManager,
|
||||
policyManager: PolicyManager,
|
||||
featureFlagManager: FeatureFlagManager,
|
||||
firstTimeActionManager: FirstTimeActionManager,
|
||||
): AuthRepository = AuthRepositoryImpl(
|
||||
accountsService = accountsService,
|
||||
devicesService = devicesService,
|
||||
|
@ -79,5 +81,6 @@ object AuthRepositoryModule {
|
|||
pushManager = pushManager,
|
||||
policyManager = policyManager,
|
||||
featureFlagManager = featureFlagManager,
|
||||
firstTimeActionManager = firstTimeActionManager,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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.repository.model.UserState.Account
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.FirstTimeState
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||
|
||||
/**
|
||||
|
@ -95,21 +96,4 @@ data class UserState(
|
|||
val hasLoginApprovingDevice: 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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.UserKeyConnectorState
|
||||
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 kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -192,42 +191,3 @@ val AuthDiskSource.currentOnboardingStatus: OnboardingStatus?
|
|||
.userState
|
||||
?.activeUserId
|
||||
?.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,
|
||||
)
|
||||
|
|
|
@ -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.UserStateJson
|
||||
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.UserKeyConnectorState
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserOrganizations
|
||||
|
@ -111,7 +112,7 @@ fun UserStateJson.toUserState(
|
|||
userIsUsingKeyConnectorList: List<UserKeyConnectorState>,
|
||||
hasPendingAccountAddition: Boolean,
|
||||
onboardingStatus: OnboardingStatus?,
|
||||
firstTimeState: UserState.FirstTimeState,
|
||||
firstTimeState: FirstTimeState,
|
||||
isBiometricsEnabledProvider: (userId: String) -> Boolean,
|
||||
vaultUnlockTypeProvider: (userId: String) -> VaultUnlockType,
|
||||
isDeviceTrustedProvider: (userId: String) -> Boolean,
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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,
|
||||
)
|
||||
}
|
|
@ -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.FeatureFlagManager
|
||||
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.NetworkConfigManagerImpl
|
||||
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.ServerConfigRepository
|
||||
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 dagger.Module
|
||||
import dagger.Provides
|
||||
|
@ -273,4 +276,20 @@ object PlatformManagerModule {
|
|||
fun provideResourceCacheManager(
|
||||
@ApplicationContext 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,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
}
|
|
@ -160,24 +160,6 @@ interface SettingsRepository {
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -6,7 +6,6 @@ import com.x8bit.bitwarden.BuildConfig
|
|||
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.UserFingerprintResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.util.activeUserIdChangesFlow
|
||||
import com.x8bit.bitwarden.data.auth.repository.util.policyInformation
|
||||
import com.x8bit.bitwarden.data.autofill.accessibility.manager.AccessibilityEnabledManager
|
||||
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.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
|
@ -340,60 +337,6 @@ class SettingsRepositoryImpl(
|
|||
?: 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 {
|
||||
policyManager
|
||||
.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
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.x8bit.bitwarden.ui.platform.feature.settings
|
|||
import androidx.compose.material3.Text
|
||||
import androidx.lifecycle.viewModelScope
|
||||
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.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.util.BackgroundEvent
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.Text
|
||||
|
@ -22,19 +22,19 @@ import javax.inject.Inject
|
|||
*/
|
||||
@HiltViewModel
|
||||
class SettingsViewModel @Inject constructor(
|
||||
settingsRepository: SettingsRepository,
|
||||
specialCircumstanceManager: SpecialCircumstanceManager,
|
||||
firstTimeActionManager: FirstTimeActionManager,
|
||||
) : BaseViewModel<SettingsState, SettingsEvent, SettingsAction>(
|
||||
initialState = SettingsState(
|
||||
securityCount = settingsRepository.allSecuritySettingsBadgeCountFlow.value,
|
||||
autoFillCount = settingsRepository.allAutofillSettingsBadgeCountFlow.value,
|
||||
securityCount = firstTimeActionManager.allSecuritySettingsBadgeCountFlow.value,
|
||||
autoFillCount = firstTimeActionManager.allAutofillSettingsBadgeCountFlow.value,
|
||||
),
|
||||
) {
|
||||
|
||||
init {
|
||||
combine(
|
||||
settingsRepository.allSecuritySettingsBadgeCountFlow,
|
||||
settingsRepository.allAutofillSettingsBadgeCountFlow,
|
||||
firstTimeActionManager.allSecuritySettingsBadgeCountFlow,
|
||||
firstTimeActionManager.allAutofillSettingsBadgeCountFlow,
|
||||
) { securityCount, autofillCount ->
|
||||
SettingsAction.Internal.SettingsNotificationCountUpdate(
|
||||
securityCount = securityCount,
|
||||
|
|
|
@ -5,9 +5,9 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
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.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.util.BackgroundEvent
|
||||
import com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar.model.VaultUnlockedNavBarTab
|
||||
|
@ -24,13 +24,13 @@ import javax.inject.Inject
|
|||
class VaultUnlockedNavBarViewModel @Inject constructor(
|
||||
authRepository: AuthRepository,
|
||||
specialCircumstancesManager: SpecialCircumstanceManager,
|
||||
settingsRepository: SettingsRepository,
|
||||
firstTimeActionManager: FirstTimeActionManager,
|
||||
) : BaseViewModel<VaultUnlockedNavBarState, VaultUnlockedNavBarEvent, VaultUnlockedNavBarAction>(
|
||||
initialState = VaultUnlockedNavBarState(
|
||||
vaultNavBarLabelRes = R.string.my_vault,
|
||||
vaultNavBarContentDescriptionRes = R.string.my_vault,
|
||||
notificationState = VaultUnlockedNavBarNotificationState(
|
||||
settingsTabNotificationCount = settingsRepository.allSettingsBadgeCountFlow.value,
|
||||
settingsTabNotificationCount = firstTimeActionManager.allSettingsBadgeCountFlow.value,
|
||||
),
|
||||
),
|
||||
) {
|
||||
|
@ -42,7 +42,7 @@ class VaultUnlockedNavBarViewModel @Inject constructor(
|
|||
}
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
settingsRepository
|
||||
firstTimeActionManager
|
||||
.allSettingsBadgeCountFlow
|
||||
.onEach {
|
||||
sendAction(VaultUnlockedNavBarAction.Internal.SettingsNotificationCountUpdate(it))
|
||||
|
|
|
@ -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.repository.AuthRepository
|
||||
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.UserState
|
||||
import com.x8bit.bitwarden.data.auth.util.getCompleteRegistrationDataIntentOrNull
|
||||
|
@ -1156,7 +1157,7 @@ private val DEFAULT_STATE: MainState = MainState(
|
|||
isScreenCaptureAllowed = true,
|
||||
)
|
||||
|
||||
private val DEFAULT_FIRST_TIME_STATE = UserState.FirstTimeState(
|
||||
private val DEFAULT_FIRST_TIME_STATE = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
)
|
||||
|
||||
|
|
|
@ -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.DeleteAccountResult
|
||||
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.LoginResult
|
||||
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.UserKeyConnectorState
|
||||
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.ValidatePinResult
|
||||
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.network.model.ConfigResponseJson
|
||||
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.PushManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||
|
@ -244,6 +245,11 @@ class AuthRepositoryTest {
|
|||
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(
|
||||
accountsService = accountsService,
|
||||
devicesService = devicesService,
|
||||
|
@ -265,6 +271,7 @@ class AuthRepositoryTest {
|
|||
pushManager = pushManager,
|
||||
policyManager = policyManager,
|
||||
featureFlagManager = featureFlagManager,
|
||||
firstTimeActionManager = firstTimeActionManager,
|
||||
)
|
||||
|
||||
@BeforeEach
|
||||
|
@ -6544,7 +6551,7 @@ class AuthRepositoryTest {
|
|||
),
|
||||
)
|
||||
|
||||
private val FIRST_TIME_STATE = UserState.FirstTimeState(
|
||||
private val FIRST_TIME_STATE = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
)
|
||||
|
||||
|
|
|
@ -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.UserKeyConnectorState
|
||||
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.vault.datasource.network.model.OrganizationType
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockOrganization
|
||||
|
@ -507,48 +506,6 @@ class AuthDiskSourceExtensionsTest {
|
|||
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"
|
||||
|
|
|
@ -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.TrustedDeviceUserDecryptionOptionsJson
|
||||
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.UserAccountTokens
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserKeyConnectorState
|
||||
|
@ -358,7 +359,7 @@ class UserStateJsonExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.NOT_STARTED,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -428,7 +429,7 @@ class UserStateJsonExtensionsTest {
|
|||
vaultUnlockTypeProvider = { VaultUnlockType.PIN },
|
||||
isDeviceTrustedProvider = { false },
|
||||
onboardingStatus = OnboardingStatus.NOT_STARTED,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -466,7 +467,7 @@ class UserStateJsonExtensionsTest {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.NOT_STARTED,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
hasPendingAccountAddition = true,
|
||||
|
@ -532,7 +533,7 @@ class UserStateJsonExtensionsTest {
|
|||
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
|
||||
isDeviceTrustedProvider = { false },
|
||||
onboardingStatus = OnboardingStatus.NOT_STARTED,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -576,7 +577,7 @@ class UserStateJsonExtensionsTest {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = true,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
hasPendingAccountAddition = true,
|
||||
|
@ -645,7 +646,7 @@ class UserStateJsonExtensionsTest {
|
|||
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
|
||||
isDeviceTrustedProvider = { true },
|
||||
onboardingStatus = null,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -689,7 +690,7 @@ class UserStateJsonExtensionsTest {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = true,
|
||||
onboardingStatus = OnboardingStatus.AUTOFILL_SETUP,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
hasPendingAccountAddition = true,
|
||||
|
@ -758,7 +759,7 @@ class UserStateJsonExtensionsTest {
|
|||
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
|
||||
isDeviceTrustedProvider = { true },
|
||||
onboardingStatus = OnboardingStatus.AUTOFILL_SETUP,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -802,7 +803,7 @@ class UserStateJsonExtensionsTest {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = true,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
hasPendingAccountAddition = true,
|
||||
|
@ -871,7 +872,7 @@ class UserStateJsonExtensionsTest {
|
|||
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
|
||||
isDeviceTrustedProvider = { true },
|
||||
onboardingStatus = null,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -919,7 +920,7 @@ class UserStateJsonExtensionsTest {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = true,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
hasPendingAccountAddition = true,
|
||||
|
@ -988,7 +989,7 @@ class UserStateJsonExtensionsTest {
|
|||
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
|
||||
isDeviceTrustedProvider = { true },
|
||||
onboardingStatus = null,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -1017,7 +1018,7 @@ class UserStateJsonExtensionsTest {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
hasPendingAccountAddition = true,
|
||||
|
@ -1066,7 +1067,7 @@ class UserStateJsonExtensionsTest {
|
|||
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
|
||||
isDeviceTrustedProvider = { true },
|
||||
onboardingStatus = null,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -1095,7 +1096,7 @@ class UserStateJsonExtensionsTest {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = true,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
hasPendingAccountAddition = true,
|
||||
|
@ -1146,7 +1147,7 @@ class UserStateJsonExtensionsTest {
|
|||
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
|
||||
isDeviceTrustedProvider = { true },
|
||||
onboardingStatus = null,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -1191,7 +1192,7 @@ class UserStateJsonExtensionsTest {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = true,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
hasPendingAccountAddition = true,
|
||||
|
@ -1262,7 +1263,7 @@ class UserStateJsonExtensionsTest {
|
|||
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
|
||||
isDeviceTrustedProvider = { true },
|
||||
onboardingStatus = null,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -1306,7 +1307,7 @@ class UserStateJsonExtensionsTest {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = true,
|
||||
onboardingStatus = OnboardingStatus.AUTOFILL_SETUP,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = false,
|
||||
),
|
||||
),
|
||||
|
@ -1377,7 +1378,7 @@ class UserStateJsonExtensionsTest {
|
|||
vaultUnlockTypeProvider = { VaultUnlockType.MASTER_PASSWORD },
|
||||
isDeviceTrustedProvider = { true },
|
||||
onboardingStatus = OnboardingStatus.AUTOFILL_SETUP,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = false,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -24,6 +24,7 @@ import com.bitwarden.sdk.Fido2CredentialStore
|
|||
import com.bitwarden.vault.CipherView
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.VaultUnlockType
|
||||
import com.x8bit.bitwarden.data.autofill.fido2.manager.Fido2CredentialManager
|
||||
|
@ -537,7 +538,7 @@ private fun createMockAccounts(number: Int): List<UserState.Account> {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
)
|
|
@ -1234,71 +1234,6 @@ class SettingsRepositoryTest {
|
|||
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"
|
||||
|
|
|
@ -5,6 +5,7 @@ import app.cash.turbine.test
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.platform.manager.BiometricsEncryptionManager
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
|
@ -388,7 +389,7 @@ private val DEFAULT_USER_ACCOUNT = UserState.Account(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.ACCOUNT_LOCK_SETUP,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
|
||||
private val CIPHER = mockk<Cipher>()
|
||||
|
|
|
@ -5,6 +5,7 @@ import app.cash.turbine.test
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.VaultUnlockType
|
||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||
|
@ -88,7 +89,7 @@ class LandingViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -226,7 +227,7 @@ class LandingViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
val userState = UserState(
|
||||
activeUserId = "activeUserId",
|
||||
|
@ -283,7 +284,7 @@ class LandingViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
val userState = UserState(
|
||||
activeUserId = "activeUserId",
|
||||
|
@ -344,7 +345,7 @@ class LandingViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
val userState = UserState(
|
||||
activeUserId = "activeUserId",
|
||||
|
@ -521,7 +522,7 @@ class LandingViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
|
||||
val userState = UserState(
|
||||
|
@ -557,7 +558,7 @@ class LandingViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
|
||||
val userState = UserState(
|
||||
|
|
|
@ -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.OnboardingStatus
|
||||
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.LoginResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
|
@ -131,7 +132,7 @@ class LoginViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -5,6 +5,7 @@ import app.cash.turbine.test
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.RemovePasswordResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
|
@ -167,7 +168,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
|
||||
private val DEFAULT_USER_STATE = UserState(
|
||||
|
|
|
@ -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.repository.AuthRepository
|
||||
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.UserState
|
||||
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
||||
|
@ -276,7 +277,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
|
||||
private val DEFAULT_USER_STATE = UserState(
|
||||
|
|
|
@ -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.OnboardingStatus
|
||||
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.UserState
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
|
||||
|
@ -219,7 +220,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -259,7 +260,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
|
||||
),
|
||||
),
|
||||
|
@ -1134,7 +1135,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
|
||||
private val DEFAULT_USER_STATE = UserState(
|
||||
|
|
|
@ -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.repository.AuthRepository
|
||||
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.Organization
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
|
@ -106,7 +107,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -143,7 +144,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -177,7 +178,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -221,7 +222,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -262,7 +263,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -303,7 +304,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = false,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -341,7 +342,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -392,7 +393,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -427,7 +428,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -467,7 +468,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -506,7 +507,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
trustedDevice = null,
|
||||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
firstTimeState = UserState.FirstTimeState(false),
|
||||
firstTimeState = FirstTimeState(false),
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
),
|
||||
),
|
||||
|
@ -548,7 +549,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -591,7 +592,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -641,7 +642,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -691,7 +692,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -736,7 +737,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -780,7 +781,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -859,7 +860,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -913,7 +914,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -975,7 +976,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -1017,7 +1018,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -1054,7 +1055,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -1089,7 +1090,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.NOT_STARTED,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -1127,7 +1128,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.ACCOUNT_LOCK_SETUP,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -1165,7 +1166,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.AUTOFILL_SETUP,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -1203,7 +1204,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.FINAL_STEP,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -1241,7 +1242,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.NOT_STARTED,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -1279,7 +1280,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
@ -1317,7 +1318,7 @@ class RootNavViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(
|
||||
firstTimeState = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.bitwarden.vault.LoginUriView
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.ValidatePasswordResult
|
||||
import com.x8bit.bitwarden.data.autofill.accessibility.manager.AccessibilitySelectionManager
|
||||
|
@ -1537,7 +1538,7 @@ private val DEFAULT_USER_STATE = UserState(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package com.x8bit.bitwarden.ui.platform.feature.settings
|
||||
|
||||
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.model.SpecialCircumstance
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
|
@ -20,7 +20,7 @@ class SettingsViewModelTest : BaseViewModelTest() {
|
|||
|
||||
private val mutableAutofillBadgeCountFlow = MutableStateFlow(0)
|
||||
private val mutableSecurityBadgeCountFlow = MutableStateFlow(0)
|
||||
private val settingsRepository = mockk<SettingsRepository> {
|
||||
private val firstTimeManager = mockk<FirstTimeActionManager> {
|
||||
every { allSecuritySettingsBadgeCountFlow } returns mutableSecurityBadgeCountFlow
|
||||
every { allAutofillSettingsBadgeCountFlow } returns mutableAutofillBadgeCountFlow
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ class SettingsViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
|
||||
private fun createViewModel() = SettingsViewModel(
|
||||
settingsRepository = settingsRepository,
|
||||
firstTimeActionManager = firstTimeManager,
|
||||
specialCircumstanceManager = specialCircumstanceManager,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import app.cash.turbine.test
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.UserFingerprintResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
|
@ -792,7 +793,7 @@ private val DEFAULT_USER_STATE = UserState(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -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.repository.AuthRepository
|
||||
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.ValidatePasswordResult
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||
|
@ -244,7 +245,7 @@ private val DEFAULT_USER_STATE: UserState = UserState(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -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.AuthRequestUpdatesResult
|
||||
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.platform.manager.SpecialCircumstanceManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.PasswordlessRequestData
|
||||
|
@ -372,7 +373,7 @@ private val DEFAULT_USER_STATE = UserState(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -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.sdk.model.PasswordStrength
|
||||
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.RequestOtpResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
|
@ -724,7 +725,7 @@ private val DEFAULT_USER_STATE = UserState(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -4,9 +4,9 @@ import app.cash.turbine.test
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
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.model.SpecialCircumstance
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
|
@ -29,7 +29,7 @@ class VaultUnlockedNavBarViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
|
||||
private val mutableSettingsBadgeCountFlow = MutableStateFlow(0)
|
||||
private val settingsRepository: SettingsRepository = mockk {
|
||||
private val firstTimeActionManager: FirstTimeActionManager = mockk {
|
||||
every { allSettingsBadgeCountFlow } returns mutableSettingsBadgeCountFlow
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,7 @@ class VaultUnlockedNavBarViewModelTest : BaseViewModelTest() {
|
|||
VaultUnlockedNavBarViewModel(
|
||||
authRepository = authRepository,
|
||||
specialCircumstancesManager = specialCircumstancesManager,
|
||||
settingsRepository = settingsRepository,
|
||||
firstTimeActionManager = firstTimeActionManager,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.bitwarden.generators.PasswordGeneratorRequest
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.platform.manager.PolicyManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||
|
@ -2408,7 +2409,7 @@ private val DEFAULT_USER_STATE = UserState(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.bitwarden.send.SendView
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.UserState
|
||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||
|
@ -1103,7 +1104,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
|
||||
private val DEFAULT_USER_STATE = UserState(
|
||||
|
|
|
@ -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.repository.AuthRepository
|
||||
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.UserState
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
|
||||
|
@ -3965,7 +3966,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
hasPendingAccountAddition = false,
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.bitwarden.vault.SecureNoteType
|
|||
import com.bitwarden.vault.SecureNoteView
|
||||
import com.x8bit.bitwarden.R
|
||||
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.UserState
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
|
||||
|
@ -513,7 +514,7 @@ class CipherViewExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.bitwarden.vault.CipherView
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.platform.repository.model.DataState
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||
|
@ -564,7 +565,7 @@ private val DEFAULT_USER_STATE = UserState(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -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.repository.AuthRepository
|
||||
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.ValidatePasswordResult
|
||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||
|
@ -2581,7 +2582,7 @@ class VaultItemViewModelTest : BaseViewModelTest() {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.bitwarden.vault.CipherView
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.UserState
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
|
||||
|
@ -4032,7 +4033,7 @@ private val DEFAULT_ACCOUNT = UserState.Account(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
|
||||
private val DEFAULT_USER_STATE = UserState(
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.bitwarden.vault.CollectionView
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.UserState
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
|
@ -515,7 +516,7 @@ private val DEFAULT_USER_STATE = UserState(
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.x8bit.bitwarden.ui.vault.feature.movetoorganization.util
|
|||
|
||||
import com.x8bit.bitwarden.R
|
||||
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.UserState
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||
|
@ -130,7 +131,7 @@ private fun createMockUserState(hasOrganizations: Boolean = true): UserState =
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -4,6 +4,7 @@ import app.cash.turbine.test
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
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.SwitchAccountResult
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
|
@ -1639,7 +1640,7 @@ private val VAULT_FILTER_DATA = VaultFilterData(
|
|||
private val DEFAULT_STATE: VaultState =
|
||||
createMockVaultState(viewState = VaultState.ViewState.Loading)
|
||||
|
||||
private val DEFAULT_FIRST_TIME_STATE = UserState.FirstTimeState(
|
||||
private val DEFAULT_FIRST_TIME_STATE = FirstTimeState(
|
||||
showImportLoginsCard = true,
|
||||
)
|
||||
|
||||
|
|
|
@ -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.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.UserState
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||
|
@ -87,7 +88,7 @@ class UserStateExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
UserState.Account(
|
||||
userId = "lockedUserId",
|
||||
|
@ -114,7 +115,7 @@ class UserStateExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
UserState.Account(
|
||||
userId = "unlockedUserId",
|
||||
|
@ -145,7 +146,7 @@ class UserStateExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
UserState.Account(
|
||||
userId = "loggedOutUserId",
|
||||
|
@ -176,7 +177,7 @@ class UserStateExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -222,7 +223,7 @@ class UserStateExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
.toAccountSummary(isActive = true),
|
||||
)
|
||||
|
@ -266,7 +267,7 @@ class UserStateExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
.toAccountSummary(isActive = false),
|
||||
)
|
||||
|
@ -314,7 +315,7 @@ class UserStateExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -342,7 +343,7 @@ class UserStateExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
.toVaultFilterData(isIndividualVaultDisabled = false),
|
||||
)
|
||||
|
@ -399,7 +400,7 @@ class UserStateExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
.toVaultFilterData(
|
||||
isIndividualVaultDisabled = false,
|
||||
|
@ -457,7 +458,7 @@ class UserStateExtensionsTest {
|
|||
hasMasterPassword = true,
|
||||
isUsingKeyConnector = false,
|
||||
onboardingStatus = OnboardingStatus.COMPLETE,
|
||||
firstTimeState = UserState.FirstTimeState(showImportLoginsCard = true),
|
||||
firstTimeState = FirstTimeState(showImportLoginsCard = true),
|
||||
)
|
||||
.toVaultFilterData(
|
||||
isIndividualVaultDisabled = true,
|
||||
|
|
Loading…
Reference in a new issue