PM-22397: Remove custom deletion date (#5311)

This commit is contained in:
David Perez
2025-06-05 14:20:12 -05:00
committed by GitHub
parent a9791c3f9f
commit d2c329264c
11 changed files with 251 additions and 262 deletions

View File

@@ -62,6 +62,7 @@ fun BitwardenTextSelectionButton(
) {
Column(
modifier = modifier
.defaultMinSize(minHeight = 60.dp)
.clearAndSetSemantics {
role = semanticRole
contentDescription = supportingText

View File

@@ -32,6 +32,7 @@ import com.x8bit.bitwarden.ui.platform.manager.permissions.PermissionsManagerImp
import com.x8bit.bitwarden.ui.platform.manager.review.AppReviewManager
import com.x8bit.bitwarden.ui.platform.manager.review.AppReviewManagerImpl
import com.x8bit.bitwarden.ui.platform.model.FeatureFlagsState
import java.time.Clock
/**
* Helper [Composable] that wraps a [content] and provides manager classes via [CompositionLocal].
@@ -43,8 +44,9 @@ fun LocalManagerProvider(
appResumeStateManager: AppResumeStateManager = AppResumeStateManagerImpl(),
appReviewManager: AppReviewManager = AppReviewManagerImpl(activity = activity),
biometricsManager: BiometricsManager = BiometricsManagerImpl(activity = activity),
clock: Clock = Clock.systemDefaultZone(),
exitManager: ExitManager = ExitManagerImpl(activity = activity),
intentManager: IntentManager = IntentManagerImpl(context = activity),
intentManager: IntentManager = IntentManagerImpl(context = activity, clock = clock),
credentialProviderCompletionManager: CredentialProviderCompletionManager =
createCredentialProviderCompletionManager(activity = activity),
keyChainManager: KeyChainManager = KeyChainManagerImpl(activity = activity),
@@ -57,6 +59,7 @@ fun LocalManagerProvider(
LocalAppResumeStateManager provides appResumeStateManager,
LocalAppReviewManager provides appReviewManager,
LocalBiometricsManager provides biometricsManager,
LocalClock provides clock,
LocalExitManager provides exitManager,
LocalCredentialProviderCompletionManager provides credentialProviderCompletionManager,
LocalIntentManager provides intentManager,
@@ -83,6 +86,11 @@ val LocalBiometricsManager: ProvidableCompositionLocal<BiometricsManager> = comp
error("CompositionLocal BiometricsManager not present")
}
/**
* Provides access to the clock throughout the app.
*/
val LocalClock: ProvidableCompositionLocal<Clock> = compositionLocalOf { Clock.systemDefaultZone() }
/**
* Provides access to the exit manager throughout the app.
*/

View File

@@ -12,6 +12,7 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import java.time.Clock
import javax.inject.Singleton
/**
@@ -25,9 +26,11 @@ class PlatformUiManagerModule {
@Singleton
fun provideIntentManager(
@ApplicationContext context: Context,
clock: Clock,
): IntentManager =
IntentManagerImpl(
context = context,
clock = clock,
)
@Provides

View File

@@ -85,7 +85,7 @@ const val EXTRA_KEY_UV_PERFORMED_DURING_UNLOCK: String = "uv_performed_during_un
@OmitFromCoverage
class IntentManagerImpl(
private val context: Context,
private val clock: Clock = Clock.systemDefaultZone(),
private val clock: Clock,
) : IntentManager {
override fun startActivity(intent: Intent) {
try {

View File

@@ -43,7 +43,6 @@ import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.components.card.BitwardenInfoCalloutCard
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
import com.x8bit.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider
import com.x8bit.bitwarden.ui.platform.components.field.BitwardenPasswordField
import com.x8bit.bitwarden.ui.platform.components.field.BitwardenTextField
import com.x8bit.bitwarden.ui.platform.components.header.BitwardenExpandingHeader
@@ -51,6 +50,8 @@ import com.x8bit.bitwarden.ui.platform.components.header.BitwardenListHeaderText
import com.x8bit.bitwarden.ui.platform.components.stepper.BitwardenStepper
import com.x8bit.bitwarden.ui.platform.components.toggle.BitwardenSwitch
import com.x8bit.bitwarden.ui.platform.manager.permissions.PermissionsManager
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.components.AddEditSendCustomDateChooser
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.components.AddEditSendDeletionDateChooser
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.handlers.AddEditSendHandlers
/**
@@ -138,48 +139,23 @@ fun AddEditSendContent(
if (isAddMode) {
AddEditSendDeletionDateChooser(
onDateSelect = addSendHandlers.onDeletionDateChange,
isEnabled = !policyDisablesSend,
modifier = Modifier
.testTag("SendDeletionOptionsPicker")
.fillMaxWidth()
.standardHorizontalMargin(),
dateFormatPattern = state.common.dateFormatPattern,
timeFormatPattern = state.common.timeFormatPattern,
currentZonedDateTime = state.common.deletionDate,
onDateSelect = addSendHandlers.onDeletionDateChange,
isEnabled = !policyDisablesSend,
)
} else {
Column(
AddEditSendCustomDateChooser(
originalSelection = state.common.deletionDate,
isEnabled = !policyDisablesSend,
onDateSelect = addSendHandlers.onDeletionDateChange,
modifier = Modifier
.testTag("SendCustomDeletionDatePicker")
.fillMaxWidth()
.standardHorizontalMargin()
.defaultMinSize(minHeight = 60.dp)
.cardStyle(cardStyle = CardStyle.Full, paddingVertical = 0.dp),
) {
AddEditSendCustomDateChooser(
modifier = Modifier
.testTag("SendCustomDeletionDatePicker")
.fillMaxWidth(),
dateLabel = stringResource(id = R.string.deletion_date),
timeLabel = stringResource(id = R.string.deletion_time),
dateFormatPattern = state.common.dateFormatPattern,
timeFormatPattern = state.common.timeFormatPattern,
currentZonedDateTime = state.common.deletionDate,
isEnabled = !policyDisablesSend,
onDateSelect = { addSendHandlers.onDeletionDateChange(requireNotNull(it)) },
)
BitwardenHorizontalDivider(modifier = Modifier.padding(start = 16.dp))
Spacer(modifier = Modifier.height(height = 12.dp))
Text(
text = stringResource(id = R.string.deletion_date_info),
style = BitwardenTheme.typography.bodySmall,
color = BitwardenTheme.colorScheme.text.secondary,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.height(height = 12.dp))
}
.standardHorizontalMargin(),
)
}
AddEditSendOptions(

View File

@@ -1,88 +0,0 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addedit
import androidx.compose.foundation.layout.Row
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenDateSelectButton
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTimeSelectButton
import com.x8bit.bitwarden.ui.platform.util.orNow
import java.time.ZonedDateTime
import java.time.temporal.ChronoUnit
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes
/**
* Displays a UI for selecting a customizable date and time.
*
* @param dateLabel The display label for the date selection field.
* @param timeLabel The display label for the time selection field.
* @param currentZonedDateTime The currently selected time, `null` when no time is selected yet.
* @param dateFormatPattern The pattern to use when displaying the date.
* @param timeFormatPattern The pattern for displaying the time.
* @param onDateSelect The callback for being notified of updates to the selected date and time.
* This will only be `null` when there is no selected time.
* @param isEnabled Whether the button is enabled.
* @param modifier A [Modifier] that you can use to apply custom modifications to the composable.
*/
@Composable
fun AddEditSendCustomDateChooser(
dateLabel: String,
timeLabel: String,
currentZonedDateTime: ZonedDateTime?,
dateFormatPattern: String,
timeFormatPattern: String,
onDateSelect: (ZonedDateTime?) -> Unit,
isEnabled: Boolean,
modifier: Modifier = Modifier,
) {
// This tracks the date component (year, month, and day) and ignores lower level
// components.
var date: ZonedDateTime? by remember { mutableStateOf(currentZonedDateTime) }
// This tracks just the time component (hours and minutes) and ignores the higher level
// components. 0 representing midnight and counting up from there.
var timeMillis: Long by remember {
mutableLongStateOf(
currentZonedDateTime.orNow().let {
it.hour.hours.inWholeMilliseconds + it.minute.minutes.inWholeMilliseconds
},
)
}
val derivedDateTimeMillis: ZonedDateTime? by remember {
derivedStateOf { date?.plus(timeMillis, ChronoUnit.MILLIS) }
}
Row(
modifier = modifier,
) {
BitwardenDateSelectButton(
modifier = Modifier.weight(1f),
label = dateLabel,
formatPattern = dateFormatPattern,
currentZonedDateTime = currentZonedDateTime,
isEnabled = isEnabled,
onDateSelect = {
date = it
onDateSelect(derivedDateTimeMillis)
},
cardStyle = null,
)
BitwardenTimeSelectButton(
modifier = Modifier.weight(1f),
label = timeLabel,
formatPattern = timeFormatPattern,
currentZonedDateTime = currentZonedDateTime,
isEnabled = isEnabled,
onTimeSelect = { hour, minute ->
timeMillis = hour.hours.inWholeMilliseconds + minute.minutes.inWholeMilliseconds
onDateSelect(derivedDateTimeMillis)
},
cardStyle = null,
)
}
}

View File

@@ -1,132 +0,0 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addedit
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.bitwarden.ui.platform.base.util.cardStyle
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.platform.theme.BitwardenTheme
import com.bitwarden.ui.util.Text
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider
import com.x8bit.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton
import kotlinx.collections.immutable.toImmutableList
import java.time.ZonedDateTime
import java.time.temporal.ChronoUnit
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.hours
/**
* Displays UX for choosing deletion date of a send.
*/
@Suppress("LongMethod")
@Composable
fun AddEditSendDeletionDateChooser(
currentZonedDateTime: ZonedDateTime,
dateFormatPattern: String,
timeFormatPattern: String,
onDateSelect: (ZonedDateTime) -> Unit,
isEnabled: Boolean,
modifier: Modifier = Modifier,
) {
val defaultOption = DeletionOptions.SEVEN_DAYS
val options = DeletionOptions.entries.associateWith { it.text() }
var selectedOption: DeletionOptions by rememberSaveable { mutableStateOf(defaultOption) }
Column(
modifier = modifier
.defaultMinSize(minHeight = 60.dp)
.cardStyle(cardStyle = CardStyle.Full, paddingVertical = 0.dp),
) {
BitwardenMultiSelectButton(
label = stringResource(id = R.string.deletion_date),
isEnabled = isEnabled,
options = options.values.toImmutableList(),
selectedOption = selectedOption.text(),
onOptionSelected = { selected ->
selectedOption = options.entries.first { it.value == selected }.key
if (selectedOption != DeletionOptions.CUSTOM) {
onDateSelect(
// Add the appropriate milliseconds offset based on the selected option
ZonedDateTime.now().plus(selectedOption.offsetMillis, ChronoUnit.MILLIS),
)
}
},
insets = PaddingValues(top = 6.dp, bottom = 4.dp),
cardStyle = null,
)
AnimatedVisibility(visible = selectedOption == DeletionOptions.CUSTOM) {
Column {
BitwardenHorizontalDivider(modifier = Modifier.padding(start = 16.dp))
AddEditSendCustomDateChooser(
dateLabel = stringResource(id = R.string.deletion_date),
timeLabel = stringResource(id = R.string.deletion_time),
currentZonedDateTime = currentZonedDateTime,
dateFormatPattern = dateFormatPattern,
timeFormatPattern = timeFormatPattern,
onDateSelect = { onDateSelect(requireNotNull(it)) },
isEnabled = isEnabled,
)
}
}
BitwardenHorizontalDivider(modifier = Modifier.padding(start = 16.dp))
Spacer(modifier = Modifier.height(height = 12.dp))
Text(
text = stringResource(id = R.string.deletion_date_info),
style = BitwardenTheme.typography.bodySmall,
color = BitwardenTheme.colorScheme.text.secondary,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.height(height = 12.dp))
}
}
private enum class DeletionOptions(
val text: Text,
val offsetMillis: Long,
) {
ONE_HOUR(
text = R.string.one_hour.asText(),
offsetMillis = 1.hours.inWholeMilliseconds,
),
ONE_DAY(
text = R.string.one_day.asText(),
offsetMillis = 1.days.inWholeMilliseconds,
),
TWO_DAYS(
text = R.string.two_days.asText(),
offsetMillis = 2.days.inWholeMilliseconds,
),
THREE_DAYS(
text = R.string.three_days.asText(),
offsetMillis = 3.days.inWholeMilliseconds,
),
SEVEN_DAYS(
text = R.string.seven_days.asText(),
offsetMillis = 7.days.inWholeMilliseconds,
),
THIRTY_DAYS(
text = R.string.thirty_days.asText(),
offsetMillis = 30.days.inWholeMilliseconds,
),
CUSTOM(
text = R.string.custom.asText(),
offsetMillis = -1L,
),
}

View File

@@ -759,11 +759,7 @@ data class AddEditSendState(
val expirationDate: ZonedDateTime?,
val sendUrl: String?,
val hasPassword: Boolean,
) : Parcelable {
val dateFormatPattern: String get() = "M/d/yyyy"
val timeFormatPattern: String get() = "hh:mm a"
}
) : Parcelable
/**
* Models what type the user is trying to send.

View File

@@ -0,0 +1,135 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addedit.components
import android.os.Parcelable
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.util.Text
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton
import com.x8bit.bitwarden.ui.platform.composition.LocalClock
import com.x8bit.bitwarden.ui.platform.util.toFormattedPattern
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.parcelize.Parcelize
import java.time.Clock
import java.time.ZonedDateTime
import java.time.temporal.ChronoUnit
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.hours
/**
* Displays a UI for selecting a customizable date and time.
*
* @param originalSelection The originally selected time value, this cannot be changed after being
* set.
* @param onDateSelect The callback for being notified of updates to the selected date and time.
* @param isEnabled Whether the button is enabled.
* @param modifier A [Modifier] that you can use to apply custom modifications to the composable.
* @param clock The clock used for formatting and timezone purposes.
*/
@Composable
fun AddEditSendCustomDateChooser(
originalSelection: ZonedDateTime,
onDateSelect: (ZonedDateTime) -> Unit,
isEnabled: Boolean,
modifier: Modifier = Modifier,
clock: Clock = LocalClock.current,
) {
val originalSelectionOption: CustomDeletionOption.Current = rememberSaveable {
CustomDeletionOption.Current(time = originalSelection)
}
val options = persistentMapOf(
originalSelectionOption to originalSelectionOption.getText(clock = clock)(),
CustomDeletionOption.OneHour to CustomDeletionOption.OneHour.getText(clock = clock)(),
CustomDeletionOption.OneDay to CustomDeletionOption.OneDay.getText(clock = clock)(),
CustomDeletionOption.TwoDays to CustomDeletionOption.TwoDays.getText(clock = clock)(),
CustomDeletionOption.ThreeDays to CustomDeletionOption.ThreeDays.getText(clock = clock)(),
CustomDeletionOption.SevenDays to CustomDeletionOption.SevenDays.getText(clock = clock)(),
CustomDeletionOption.ThirtyDays to CustomDeletionOption.ThirtyDays.getText(clock = clock)(),
)
var currentSelectionOption: CustomDeletionOption by rememberSaveable(originalSelectionOption) {
mutableStateOf(value = originalSelectionOption)
}
BitwardenMultiSelectButton(
label = stringResource(id = R.string.deletion_date),
isEnabled = isEnabled,
options = options.values.toImmutableList(),
selectedOption = currentSelectionOption.getText(clock = clock).invoke(),
onOptionSelected = { selected ->
currentSelectionOption = options.entries.first { it.value == selected }.key
onDateSelect(
(currentSelectionOption as? CustomDeletionOption.Current)
?.time
?: ZonedDateTime
.now(clock)
.plus(currentSelectionOption.offsetMillis, ChronoUnit.MILLIS),
)
},
supportingText = stringResource(id = R.string.deletion_date_info),
insets = PaddingValues(top = 6.dp, bottom = 4.dp),
cardStyle = CardStyle.Full,
modifier = modifier,
)
}
@Parcelize
private sealed class CustomDeletionOption : Parcelable {
abstract val offsetMillis: Long
abstract fun getText(clock: Clock): Text
@Parcelize
data class Current(
val time: ZonedDateTime,
) : CustomDeletionOption() {
override val offsetMillis: Long get() = 0L
override fun getText(
clock: Clock,
): Text = time.toFormattedPattern(pattern = "d MMM, yyyy, h:mma", clock = clock).asText()
}
@Parcelize
data object OneHour : CustomDeletionOption() {
override val offsetMillis: Long get() = 1.hours.inWholeMilliseconds
override fun getText(clock: Clock): Text = R.string.one_hour.asText()
}
@Parcelize
data object OneDay : CustomDeletionOption() {
override val offsetMillis: Long get() = 1.days.inWholeMilliseconds
override fun getText(clock: Clock): Text = R.string.one_day.asText()
}
@Parcelize
data object TwoDays : CustomDeletionOption() {
override val offsetMillis: Long get() = 2.days.inWholeMilliseconds
override fun getText(clock: Clock): Text = R.string.two_days.asText()
}
@Parcelize
data object ThreeDays : CustomDeletionOption() {
override val offsetMillis: Long get() = 3.days.inWholeMilliseconds
override fun getText(clock: Clock): Text = R.string.three_days.asText()
}
@Parcelize
data object SevenDays : CustomDeletionOption() {
override val offsetMillis: Long get() = 7.days.inWholeMilliseconds
override fun getText(clock: Clock): Text = R.string.seven_days.asText()
}
@Parcelize
data object ThirtyDays : CustomDeletionOption() {
override val offsetMillis: Long get() = 30.days.inWholeMilliseconds
override fun getText(clock: Clock): Text = R.string.thirty_days.asText()
}
}

View File

@@ -0,0 +1,85 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addedit.components
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.util.Text
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton
import com.x8bit.bitwarden.ui.platform.composition.LocalClock
import kotlinx.collections.immutable.toImmutableList
import java.time.Clock
import java.time.ZonedDateTime
import java.time.temporal.ChronoUnit
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.hours
/**
* Displays UX for choosing deletion date of a send.
*/
@Composable
fun AddEditSendDeletionDateChooser(
onDateSelect: (ZonedDateTime) -> Unit,
isEnabled: Boolean,
modifier: Modifier = Modifier,
clock: Clock = LocalClock.current,
) {
val options = DeletionOption.entries.associateWith { it.text() }
var selectedOption: DeletionOption by rememberSaveable {
mutableStateOf(value = DeletionOption.SEVEN_DAYS)
}
BitwardenMultiSelectButton(
label = stringResource(id = R.string.deletion_date),
isEnabled = isEnabled,
options = options.values.toImmutableList(),
selectedOption = selectedOption.text(),
onOptionSelected = { selected ->
selectedOption = options.entries.first { it.value == selected }.key
onDateSelect(
ZonedDateTime.now(clock).plus(selectedOption.offsetMillis, ChronoUnit.MILLIS),
)
},
supportingText = stringResource(id = R.string.deletion_date_info),
insets = PaddingValues(top = 6.dp, bottom = 4.dp),
cardStyle = CardStyle.Full,
modifier = modifier,
)
}
private enum class DeletionOption(
val text: Text,
val offsetMillis: Long,
) {
ONE_HOUR(
text = R.string.one_hour.asText(),
offsetMillis = 1.hours.inWholeMilliseconds,
),
ONE_DAY(
text = R.string.one_day.asText(),
offsetMillis = 1.days.inWholeMilliseconds,
),
TWO_DAYS(
text = R.string.two_days.asText(),
offsetMillis = 2.days.inWholeMilliseconds,
),
THREE_DAYS(
text = R.string.three_days.asText(),
offsetMillis = 3.days.inWholeMilliseconds,
),
SEVEN_DAYS(
text = R.string.seven_days.asText(),
offsetMillis = 7.days.inWholeMilliseconds,
),
THIRTY_DAYS(
text = R.string.thirty_days.asText(),
offsetMillis = 30.days.inWholeMilliseconds,
),
}

View File

@@ -16,6 +16,9 @@ import com.x8bit.bitwarden.ui.platform.manager.permissions.PermissionsManager
import com.x8bit.bitwarden.ui.platform.manager.review.AppReviewManager
import com.x8bit.bitwarden.ui.platform.model.FeatureFlagsState
import io.mockk.mockk
import java.time.Clock
import java.time.Instant
import java.time.ZoneOffset
abstract class BitwardenComposeTest : BaseComposeTest() {
@@ -32,6 +35,7 @@ abstract class BitwardenComposeTest : BaseComposeTest() {
appResumeStateManager: AppResumeStateManager = mockk(),
appReviewManager: AppReviewManager = mockk(),
biometricsManager: BiometricsManager = mockk(),
clock: Clock = Clock.fixed(Instant.parse("2023-10-27T12:00:00Z"), ZoneOffset.UTC),
exitManager: ExitManager = mockk(),
intentManager: IntentManager = mockk(),
credentialProviderCompletionManager: CredentialProviderCompletionManager = mockk(),
@@ -46,6 +50,7 @@ abstract class BitwardenComposeTest : BaseComposeTest() {
appResumeStateManager = appResumeStateManager,
appReviewManager = appReviewManager,
biometricsManager = biometricsManager,
clock = clock,
exitManager = exitManager,
intentManager = intentManager,
credentialProviderCompletionManager = credentialProviderCompletionManager,