Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.x8bit.bitwarden.ui.vault.feature.vault

import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.bitwarden.ui.platform.components.card.BitwardenActionCard
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.ui.vault.feature.vault.handlers.VaultHandlers

/**
* The action card for the vault screen.
*/
@Suppress("LongMethod")
@Composable
fun VaultActionCard(
actionCardState: VaultState.ActionCardState,
vaultHandlers: VaultHandlers,
modifier: Modifier = Modifier,
) {
when (actionCardState) {
VaultState.ActionCardState.UpgradedToPremium -> {
BitwardenActionCard(
cardTitle = stringResource(id = BitwardenString.upgraded_to_premium),
cardSubtitle = stringResource(
id = BitwardenString.you_now_have_access_to_all_advanced_security_features,
),
actionText = stringResource(id = BitwardenString.learn_more),
isExternalLink = true,
leadingContent = {
Icon(
painter = rememberVectorPainter(id = BitwardenDrawable.ic_star),
contentDescription = null,
tint = BitwardenTheme.colorScheme.icon.secondary,
)
},
onActionClick = { vaultHandlers.actionCardClick(actionCardState) },
onDismissClick = { vaultHandlers.dismissActionCardClick(actionCardState) },
modifier = modifier,
)
}

VaultState.ActionCardState.UpgradePremium -> {
BitwardenActionCard(
cardTitle = stringResource(
id = BitwardenString.unlock_advanced_security_features,
),
cardSubtitle = stringResource(
id = BitwardenString
.a_premium_plan_gives_you_more_tools_to_stay_secure_and_in_control,
),
actionText = stringResource(id = BitwardenString.learn_more),
onActionClick = { vaultHandlers.actionCardClick(actionCardState) },
onDismissClick = { vaultHandlers.dismissActionCardClick(actionCardState) },
modifier = modifier,
)
}

VaultState.ActionCardState.PremiumNeedsAttention -> {
BitwardenActionCard(
cardTitle = stringResource(id = BitwardenString.your_subscription_needs_attention),
cardSubtitle = stringResource(id = BitwardenString.check_your_plan_for_details),
actionText = stringResource(id = BitwardenString.view_plan),
onActionClick = { vaultHandlers.actionCardClick(actionCardState) },
modifier = modifier,
)
}

VaultState.ActionCardState.IntroducingArchive -> {
BitwardenActionCard(
cardTitle = stringResource(id = BitwardenString.introducing_archive),
cardSubtitle = stringResource(
id = BitwardenString.keep_items_you_dont_need_right_now_safe_but_out_sight,
),
actionText = stringResource(id = BitwardenString.go_to_archive),
leadingContent = {
Icon(
painter = rememberVectorPainter(id = BitwardenDrawable.ic_archive),
contentDescription = null,
tint = BitwardenTheme.colorScheme.icon.secondary,
)
},
onActionClick = { vaultHandlers.actionCardClick(actionCardState) },
onDismissClick = { vaultHandlers.dismissActionCardClick(actionCardState) },
modifier = modifier,
)
}

VaultState.ActionCardState.ImportItems -> {
BitwardenActionCard(
cardTitle = stringResource(id = BitwardenString.import_saved_logins),
cardSubtitle = stringResource(id = BitwardenString.use_a_computer_to_import_logins),
actionText = stringResource(id = BitwardenString.get_started),
onActionClick = { vaultHandlers.actionCardClick(actionCardState) },
onDismissClick = { vaultHandlers.dismissActionCardClick(actionCardState) },
modifier = modifier,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand All @@ -19,15 +18,12 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.bitwarden.ui.platform.base.util.standardHorizontalMargin
import com.bitwarden.ui.platform.base.util.toListItemCardStyle
import com.bitwarden.ui.platform.components.card.BitwardenActionCard
import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText
import com.bitwarden.ui.platform.components.icon.model.IconData
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenMasterPasswordDialog
import com.x8bit.bitwarden.ui.platform.components.listitem.BitwardenGroupItem
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.model.ListingItemOverflowAction
Expand Down Expand Up @@ -107,7 +103,7 @@ fun VaultContent(

actionCardState?.let {
item(key = "action_card") {
ActionCard(
VaultActionCard(
actionCardState = it,
vaultHandlers = vaultHandlers,
modifier = Modifier
Expand Down Expand Up @@ -561,80 +557,3 @@ fun VaultContent(
}
}
}

@Suppress("LongMethod")
@Composable
private fun ActionCard(
actionCardState: VaultState.ActionCardState,
vaultHandlers: VaultHandlers,
modifier: Modifier = Modifier,
) {
when (actionCardState) {
VaultState.ActionCardState.UpgradedToPremium -> {
BitwardenActionCard(
cardTitle = stringResource(id = BitwardenString.upgraded_to_premium),
cardSubtitle = stringResource(
id = BitwardenString.you_now_have_access_to_all_advanced_security_features,
),
actionText = stringResource(id = BitwardenString.learn_more),
isExternalLink = true,
leadingContent = {
Icon(
painter = rememberVectorPainter(id = BitwardenDrawable.ic_star),
contentDescription = null,
tint = BitwardenTheme.colorScheme.icon.secondary,
)
},
onActionClick = { vaultHandlers.actionCardClick(actionCardState) },
onDismissClick = { vaultHandlers.dismissActionCardClick(actionCardState) },
modifier = modifier,
)
}

VaultState.ActionCardState.UpgradePremium -> {
BitwardenActionCard(
cardTitle = stringResource(
id = BitwardenString.unlock_advanced_security_features,
),
cardSubtitle = stringResource(
id = BitwardenString
.a_premium_plan_gives_you_more_tools_to_stay_secure_and_in_control,
),
actionText = stringResource(id = BitwardenString.learn_more),
onActionClick = { vaultHandlers.actionCardClick(actionCardState) },
onDismissClick = { vaultHandlers.dismissActionCardClick(actionCardState) },
modifier = modifier,
)
}

VaultState.ActionCardState.PremiumNeedsAttention -> {
BitwardenActionCard(
cardTitle = stringResource(id = BitwardenString.your_subscription_needs_attention),
cardSubtitle = stringResource(id = BitwardenString.check_your_plan_for_details),
actionText = stringResource(id = BitwardenString.view_plan),
onActionClick = { vaultHandlers.actionCardClick(actionCardState) },
modifier = modifier,
)
}

VaultState.ActionCardState.IntroducingArchive -> {
BitwardenActionCard(
cardTitle = stringResource(id = BitwardenString.introducing_archive),
cardSubtitle = stringResource(
id = BitwardenString.keep_items_you_dont_need_right_now_safe_but_out_sight,
),
actionText = stringResource(id = BitwardenString.go_to_archive),
leadingContent = {
Icon(
painter = rememberVectorPainter(id = BitwardenDrawable.ic_archive),
contentDescription = null,
tint = BitwardenTheme.colorScheme.icon.secondary,
)
},
onActionClick = { vaultHandlers.actionCardClick(actionCardState) },
onDismissClick = { vaultHandlers.dismissActionCardClick(actionCardState) },
modifier = modifier,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import com.bitwarden.ui.platform.components.appbar.action.BitwardenSearchActionI
import com.bitwarden.ui.platform.components.appbar.model.OverflowMenuItemData
import com.bitwarden.ui.platform.components.appbar.model.TopAppBarDividerStyle
import com.bitwarden.ui.platform.components.button.model.BitwardenButtonData
import com.bitwarden.ui.platform.components.card.BitwardenActionCard
import com.bitwarden.ui.platform.components.card.actionCardExitAnimation
import com.bitwarden.ui.platform.components.content.BitwardenErrorContent
import com.bitwarden.ui.platform.components.content.BitwardenLoadingContent
Expand Down Expand Up @@ -340,19 +339,14 @@ private fun VaultScreenScaffold(
)

is VaultState.ViewState.NoItems -> {
AnimatedVisibility(
visible = state.showImportActionCard,
AnimateNullableContentVisibility(
targetState = state.actionCard,
exit = actionCardExitAnimation(),
label = "VaultNoItemsActionCard",
) {
BitwardenActionCard(
cardTitle = stringResource(BitwardenString.import_saved_logins),
cardSubtitle = stringResource(
BitwardenString.use_a_computer_to_import_logins,
),
actionText = stringResource(BitwardenString.get_started),
onActionClick = vaultHandlers.importActionCardClick,
onDismissClick = vaultHandlers.dismissImportActionCard,
) { actionCard ->
VaultActionCard(
actionCardState = actionCard,
vaultHandlers = vaultHandlers,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,6 @@ class VaultViewModel @Inject constructor(
}

is VaultAction.Internal -> handleInternalAction(action)
VaultAction.DismissImportActionCard -> handleDismissImportActionCard()
VaultAction.ImportActionCardClick -> handleImportActionCardClick()
VaultAction.LifecycleResumed -> handleLifecycleResumed()
VaultAction.SelectAddItemType -> handleSelectAddItemType()
VaultAction.DismissFlightRecorderSnackbar -> handleDismissFlightRecorderSnackbar()
Expand Down Expand Up @@ -457,6 +455,12 @@ class VaultViewModel @Inject constructor(
VaultState.ActionCardState.IntroducingArchive -> {
settingsRepository.dismissIntroducingArchiveActionCard()
}

VaultState.ActionCardState.ImportItems -> {
firstTimeActionManager.storeShowImportLoginsSettingsBadge(showBadge = true)
if (!state.showImportActionCard) return
firstTimeActionManager.storeShowImportLogins(showImportLogins = false)
}
}
}

Expand All @@ -477,9 +481,11 @@ class VaultViewModel @Inject constructor(

VaultState.ActionCardState.IntroducingArchive -> {
settingsRepository.dismissIntroducingArchiveActionCard()
sendEvent(
VaultEvent.NavigateToItemListing(VaultItemListingType.Archive),
)
sendEvent(VaultEvent.NavigateToItemListing(VaultItemListingType.Archive))
}

VaultState.ActionCardState.ImportItems -> {
sendEvent(VaultEvent.NavigateToImportLogins)
}
}
}
Expand Down Expand Up @@ -526,16 +532,6 @@ class VaultViewModel @Inject constructor(
}
}

private fun handleImportActionCardClick() {
sendEvent(VaultEvent.NavigateToImportLogins)
}

private fun handleDismissImportActionCard() {
firstTimeActionManager.storeShowImportLoginsSettingsBadge(true)
if (!state.showImportActionCard) return
firstTimeActionManager.storeShowImportLogins(false)
}

private fun handleIconLoadingSettingReceive(
action: VaultAction.Internal.IconLoadingSettingReceive,
) {
Expand Down Expand Up @@ -1789,16 +1785,30 @@ data class VaultState(
* Indicates what action card to display.
*/
val actionCard: ActionCardState?
get() = (viewState as? ViewState.Content)?.let {
ActionCardState.UpgradedToPremium
.takeIf { isUpgradedToPremiumCardEligible }
?: ActionCardState.UpgradePremium.takeIf { premiumCard == PremiumCard.UPGRADE }
?: ActionCardState.PremiumNeedsAttention.takeIf {
premiumCard == PremiumCard.NEEDS_ATTENTION
}
?: ActionCardState.IntroducingArchive.takeIf {
isPremium && !isIntroducingArchiveActionCardDismissed
}
get() = when (viewState) {
is ViewState.Content -> {
ActionCardState.UpgradedToPremium
.takeIf { isUpgradedToPremiumCardEligible }
?: ActionCardState.UpgradePremium.takeIf { premiumCard == PremiumCard.UPGRADE }
?: ActionCardState.PremiumNeedsAttention.takeIf {
premiumCard == PremiumCard.NEEDS_ATTENTION
}
?: ActionCardState.IntroducingArchive.takeIf {
isPremium && !isIntroducingArchiveActionCardDismissed
}
}

ViewState.NoItems -> {
ActionCardState.UpgradePremium.takeIf { premiumCard == PremiumCard.UPGRADE }
?: ActionCardState.PremiumNeedsAttention.takeIf {
premiumCard == PremiumCard.NEEDS_ATTENTION
}
?: ActionCardState.ImportItems.takeIf { showImportActionCard }
}

is ViewState.Error,
ViewState.Loading,
-> null
}

/**
Expand Down Expand Up @@ -2211,6 +2221,11 @@ data class VaultState(
* Indicates that the archive feature is ready for use.
*/
data object IntroducingArchive : ActionCardState()

/**
* Indicates that the import items card should be displayed.
*/
data object ImportItems : ActionCardState()
}

/**
Expand Down Expand Up @@ -2599,16 +2614,6 @@ sealed class VaultAction {
*/
data object TryAgainClick : VaultAction()

/**
* The user has dismissed the import action card.
*/
data object DismissImportActionCard : VaultAction()

/**
* The user has clicked the import action card.
*/
data object ImportActionCardClick : VaultAction()

/**
* User clicked an overflow action.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ data class VaultHandlers(
String,
) -> Unit,
val masterPasswordRepromptSubmit: (VaultState.ViewState.VaultItem, String) -> Unit,
val dismissImportActionCard: () -> Unit,
val importActionCardClick: () -> Unit,
val flightRecorderGoToSettingsClick: () -> Unit,
val dismissFlightRecorderSnackbar: () -> Unit,
val onShareCipherDecryptionErrorClick: (selectedCipherId: String) -> Unit,
Expand Down Expand Up @@ -131,12 +129,6 @@ data class VaultHandlers(
),
)
},
dismissImportActionCard = {
viewModel.trySendAction(VaultAction.DismissImportActionCard)
},
importActionCardClick = {
viewModel.trySendAction(VaultAction.ImportActionCardClick)
},
flightRecorderGoToSettingsClick = {
viewModel.trySendAction(VaultAction.FlightRecorderGoToSettingsClick)
},
Expand Down
Loading
Loading