From 202dd652290e9e9dbb4bb636f244ec6e0e53cba1 Mon Sep 17 00:00:00 2001 From: David Perez Date: Tue, 7 Oct 2025 12:04:32 -0500 Subject: [PATCH] PM-26579: Remove duplicated BitwardenScaffold from ItemListingScreen (#5978) --- .../feature/itemlisting/ItemListingScreen.kt | 830 ++++++++---------- 1 file changed, 350 insertions(+), 480 deletions(-) diff --git a/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt b/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt index cf80346dc0..d2f2d52b43 100644 --- a/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt +++ b/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt @@ -27,7 +27,6 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -41,6 +40,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -63,12 +63,12 @@ import com.bitwarden.ui.platform.base.util.EventsEffect import com.bitwarden.ui.platform.base.util.standardHorizontalMargin import com.bitwarden.ui.platform.base.util.toListItemCardStyle import com.bitwarden.ui.platform.components.appbar.BitwardenMediumTopAppBar -import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar import com.bitwarden.ui.platform.components.appbar.action.BitwardenSearchActionItem import com.bitwarden.ui.platform.components.button.BitwardenFilledButton import com.bitwarden.ui.platform.components.button.BitwardenTextButton import com.bitwarden.ui.platform.components.card.BitwardenActionCard import com.bitwarden.ui.platform.components.card.color.bitwardenCardColors +import com.bitwarden.ui.platform.components.content.BitwardenLoadingContent import com.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog import com.bitwarden.ui.platform.components.dialog.BitwardenLoadingDialog import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog @@ -107,6 +107,7 @@ fun ItemListingScreen( val state by viewModel.stateFlow.collectAsStateWithLifecycle() val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) val context = LocalContext.current + val resources = LocalResources.current val launcher = permissionsManager.getLauncher { isGranted -> if (isGranted) { viewModel.trySendAction(ItemListingAction.ScanQrCodeClick) @@ -124,13 +125,7 @@ fun ItemListingScreen( is ItemListingEvent.NavigateToQrCodeScanner -> onNavigateToQrCodeScanner() is ItemListingEvent.NavigateToManualAddItem -> onNavigateToManualKeyEntry() is ItemListingEvent.ShowToast -> { - Toast - .makeText( - context, - event.message(context.resources), - Toast.LENGTH_LONG, - ) - .show() + Toast.makeText(context, event.message(resources), Toast.LENGTH_LONG).show() } is ItemListingEvent.NavigateToEditItem -> onNavigateToEditItemScreen(event.id) @@ -164,136 +159,136 @@ fun ItemListingScreen( ItemListingDialogs( dialog = state.dialog, onDismissRequest = remember(viewModel) { - { - viewModel.trySendAction( - ItemListingAction.DialogDismiss, - ) - } + { viewModel.trySendAction(ItemListingAction.DialogDismiss) } }, onConfirmDeleteClick = remember(viewModel) { - { itemId -> - viewModel.trySendAction( - ItemListingAction.ConfirmDeleteClick(itemId = itemId), - ) - } + { viewModel.trySendAction(ItemListingAction.ConfirmDeleteClick(it)) } }, ) - when (val currentState = state.viewState) { - is ItemListingState.ViewState.Content -> { - ItemListingContent( - state = currentState, - snackbarHostState = snackbarHostState, + BitwardenScaffold( + modifier = Modifier + .fillMaxSize() + .nestedScroll(scrollBehavior.nestedScrollConnection), + topBar = { + BitwardenMediumTopAppBar( + title = stringResource(id = BitwardenString.verification_codes), scrollBehavior = scrollBehavior, - onNavigateToSearch = remember(viewModel) { - { - viewModel.trySendAction( - ItemListingAction.SearchClick, + actions = { + if (state.viewState is ItemListingState.ViewState.Content) { + BitwardenSearchActionItem( + contentDescription = stringResource(id = BitwardenString.search_codes), + onClick = onNavigateToSearch, ) } }, - onScanQrCodeClick = remember(viewModel) { - { - launcher.launch(Manifest.permission.CAMERA) - } - }, - onEnterSetupKeyClick = remember(viewModel) { - { - viewModel.trySendAction(ItemListingAction.EnterSetupKeyClick) - } - }, - onItemClick = remember(viewModel) { - { - viewModel.trySendAction( - ItemListingAction.ItemClick(it), - ) - } - }, - onDropdownMenuClick = remember(viewModel) { - { action, item -> - viewModel.trySendAction( - ItemListingAction.DropdownMenuClick( - menuAction = action, - item = item, - ), - ) - } - }, - onDownloadBitwardenClick = remember(viewModel) { - { - viewModel.trySendAction(ItemListingAction.DownloadBitwardenClick) - } - }, - onDismissDownloadBitwardenClick = remember(viewModel) { - { - viewModel.trySendAction(ItemListingAction.DownloadBitwardenDismiss) - } - }, - onSyncWithBitwardenClick = remember(viewModel) { - { - viewModel.trySendAction(ItemListingAction.SyncWithBitwardenClick) - } - }, - onDismissSyncWithBitwardenClick = remember(viewModel) { - { - viewModel.trySendAction(ItemListingAction.SyncWithBitwardenDismiss) - } - }, - onSyncLearnMoreClick = remember(viewModel) { - { viewModel.trySendAction(ItemListingAction.SyncLearnMoreClick) } - }, - onSectionExpandedClick = remember(viewModel) { - { viewModel.trySendAction(ItemListingAction.SectionExpandedClick(it)) } - }, ) - } + }, + floatingActionButton = { + BitwardenExpandableFloatingActionButton( + modifier = Modifier.testTag("AddItemButton"), + items = persistentListOf( + ItemListingExpandableFabAction.ScanQrCode( + label = BitwardenString.scan_a_qr_code.asText(), + icon = IconData.Local( + iconRes = BitwardenDrawable.ic_camera_small, + contentDescription = BitwardenString.scan_a_qr_code.asText(), + testTag = "ScanQRCodeButton", + ), + onScanQrCodeClick = remember(viewModel) { + { launcher.launch(Manifest.permission.CAMERA) } + }, + ), + ItemListingExpandableFabAction.EnterSetupKey( + label = BitwardenString.enter_key_manually.asText(), + icon = IconData.Local( + iconRes = BitwardenDrawable.ic_lock_encrypted_small, + contentDescription = BitwardenString.enter_key_manually.asText(), + testTag = "EnterSetupKeyButton", + ), + onEnterSetupKeyClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.EnterSetupKeyClick) } + }, + ), + ), + expandableFabIcon = ExpandableFabIcon( + icon = IconData.Local( + iconRes = BitwardenDrawable.ic_plus, + contentDescription = BitwardenString.add_item.asText(), + testTag = "AddItemButton", + ), + iconRotation = 45f, + ), + ) + }, + snackbarHost = { FirstTimeSyncSnackbarHost(state = snackbarHostState) }, + ) { + when (val currentState = state.viewState) { + is ItemListingState.ViewState.Content -> { + ItemListingContent( + state = currentState, + onItemClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.ItemClick(it)) } + }, + onDropdownMenuClick = remember(viewModel) { + { action, item -> + viewModel.trySendAction( + ItemListingAction.DropdownMenuClick( + menuAction = action, + item = item, + ), + ) + } + }, + onDownloadBitwardenClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.DownloadBitwardenClick) } + }, + onDismissDownloadBitwardenClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.DownloadBitwardenDismiss) } + }, + onSyncWithBitwardenClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.SyncWithBitwardenClick) } + }, + onDismissSyncWithBitwardenClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.SyncWithBitwardenDismiss) } + }, + onSyncLearnMoreClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.SyncLearnMoreClick) } + }, + onSectionExpandedClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.SectionExpandedClick(it)) } + }, + ) + } - ItemListingState.ViewState.Loading -> Unit - is ItemListingState.ViewState.NoItems, - -> { - EmptyItemListingContent( - actionCardState = currentState.actionCard, - appTheme = state.appTheme, - scrollBehavior = scrollBehavior, - onAddCodeClick = remember(viewModel) { - { - launcher.launch(Manifest.permission.CAMERA) - } - }, - onScanQrCodeClick = remember(viewModel) { - { - launcher.launch(Manifest.permission.CAMERA) - } - }, - onEnterSetupKeyClick = remember(viewModel) { - { - viewModel.trySendAction(ItemListingAction.EnterSetupKeyClick) - } - }, - onDownloadBitwardenClick = remember(viewModel) { - { - viewModel.trySendAction(ItemListingAction.DownloadBitwardenClick) - } - }, - onDismissDownloadBitwardenClick = remember(viewModel) { - { - viewModel.trySendAction(ItemListingAction.DownloadBitwardenDismiss) - } - }, - onSyncWithBitwardenClick = remember(viewModel) { - { - viewModel.trySendAction(ItemListingAction.SyncWithBitwardenClick) - } - }, - onSyncLearnMoreClick = remember(viewModel) { - { viewModel.trySendAction(ItemListingAction.SyncLearnMoreClick) } - }, - onDismissSyncWithBitwardenClick = remember(viewModel) { - { - viewModel.trySendAction(ItemListingAction.SyncWithBitwardenDismiss) - } - }, - ) + ItemListingState.ViewState.Loading -> { + BitwardenLoadingContent(modifier = Modifier.fillMaxSize()) + } + + is ItemListingState.ViewState.NoItems -> { + EmptyItemListingContent( + actionCardState = currentState.actionCard, + appTheme = state.appTheme, + onAddCodeClick = remember(viewModel) { + { launcher.launch(Manifest.permission.CAMERA) } + }, + onDownloadBitwardenClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.DownloadBitwardenClick) } + }, + onDismissDownloadBitwardenClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.DownloadBitwardenDismiss) } + }, + onSyncWithBitwardenClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.SyncWithBitwardenClick) } + }, + onSyncLearnMoreClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.SyncLearnMoreClick) } + }, + onDismissSyncWithBitwardenClick = remember(viewModel) { + { viewModel.trySendAction(ItemListingAction.SyncWithBitwardenDismiss) } + }, + ) + } } } } @@ -338,15 +333,9 @@ private fun ItemListingDialogs( } @Suppress("LongMethod") -@OptIn(ExperimentalMaterial3Api::class) @Composable private fun ItemListingContent( state: ItemListingState.ViewState.Content, - snackbarHostState: SnackbarHostState, - scrollBehavior: TopAppBarScrollBehavior, - onNavigateToSearch: () -> Unit, - onScanQrCodeClick: () -> Unit, - onEnterSetupKeyClick: () -> Unit, onItemClick: (String) -> Unit, onDropdownMenuClick: (VaultDropdownMenuAction, VerificationCodeDisplayItem) -> Unit, onDownloadBitwardenClick: () -> Unit, @@ -355,244 +344,189 @@ private fun ItemListingContent( onDismissSyncWithBitwardenClick: () -> Unit, onSyncLearnMoreClick: () -> Unit, onSectionExpandedClick: (SharedCodesDisplayState.SharedCodesAccountSection) -> Unit, + modifier: Modifier = Modifier, ) { - BitwardenScaffold( - modifier = Modifier - .fillMaxSize() - .nestedScroll(scrollBehavior.nestedScrollConnection), - topBar = { - BitwardenMediumTopAppBar( - title = stringResource(id = BitwardenString.verification_codes), - scrollBehavior = scrollBehavior, - actions = { - BitwardenSearchActionItem( - contentDescription = stringResource(id = BitwardenString.search_codes), - onClick = onNavigateToSearch, - ) - }, + var isLocalHeaderExpanded by rememberSaveable { mutableStateOf(value = true) } + LazyColumn(modifier = modifier.fillMaxSize()) { + item(key = "action_card") { + ActionCard( + actionCardState = state.actionCard, + onDownloadBitwardenClick = onDownloadBitwardenClick, + onDownloadBitwardenDismissClick = onDismissDownloadBitwardenClick, + onSyncWithBitwardenClick = onSyncWithBitwardenClick, + onSyncWithBitwardenDismissClick = onDismissSyncWithBitwardenClick, + onSyncLearnMoreClick = onSyncLearnMoreClick, + modifier = Modifier + .standardHorizontalMargin() + .padding(top = 12.dp, bottom = 16.dp) + .animateItem(), ) - }, - floatingActionButton = { - BitwardenExpandableFloatingActionButton( - modifier = Modifier.testTag("AddItemButton"), - items = persistentListOf( - ItemListingExpandableFabAction.ScanQrCode( - label = BitwardenString.scan_a_qr_code.asText(), - icon = IconData.Local( - iconRes = BitwardenDrawable.ic_camera_small, - contentDescription = BitwardenString.scan_a_qr_code.asText(), - testTag = "ScanQRCodeButton", - ), - onScanQrCodeClick = onScanQrCodeClick, - ), - ItemListingExpandableFabAction.EnterSetupKey( - label = BitwardenString.enter_key_manually.asText(), - icon = IconData.Local( - iconRes = BitwardenDrawable.ic_lock_encrypted_small, - contentDescription = BitwardenString.enter_key_manually.asText(), - testTag = "EnterSetupKeyButton", - ), - onEnterSetupKeyClick = onEnterSetupKeyClick, - ), - ), - expandableFabIcon = ExpandableFabIcon( - icon = IconData.Local( - iconRes = BitwardenDrawable.ic_plus, - contentDescription = BitwardenString.add_item.asText(), - testTag = "AddItemButton", - ), - iconRotation = 45f, - ), - ) - }, - snackbarHost = { FirstTimeSyncSnackbarHost(state = snackbarHostState) }, - ) { - var isLocalHeaderExpanded by rememberSaveable { mutableStateOf(true) } - LazyColumn( - modifier = Modifier.fillMaxSize(), - ) { - item(key = "action_card") { - ActionCard( - actionCardState = state.actionCard, - onDownloadBitwardenClick = onDownloadBitwardenClick, - onDownloadBitwardenDismissClick = onDismissDownloadBitwardenClick, - onSyncWithBitwardenClick = onSyncWithBitwardenClick, - onSyncWithBitwardenDismissClick = onDismissSyncWithBitwardenClick, - onSyncLearnMoreClick = onSyncLearnMoreClick, + } + if (state.favoriteItems.isNotEmpty()) { + item(key = "favorites_header") { + BitwardenListHeaderText( + label = stringResource(id = BitwardenString.favorites), + supportingLabel = state.favoriteItems.count().toString(), + modifier = Modifier + .fillMaxWidth() + .standardHorizontalMargin() + .padding(horizontal = 16.dp) + .animateItem(), + ) + Spacer(modifier = Modifier.height(height = 8.dp)) + } + + itemsIndexed( + items = state.favoriteItems, + key = { _, it -> "favorite_item_${it.id}" }, + ) { index, it -> + VaultVerificationCodeItem( + authCode = it.authCode, + primaryLabel = it.title, + secondaryLabel = it.subtitle, + periodSeconds = it.periodSeconds, + timeLeftSeconds = it.timeLeftSeconds, + alertThresholdSeconds = it.alertThresholdSeconds, + startIcon = it.startIcon, + onItemClick = { onItemClick(it.authCode) }, + onDropdownMenuClick = { action -> + onDropdownMenuClick(action, it) + }, + showMoveToBitwarden = it.showMoveToBitwarden, + allowLongPress = it.allowLongPressActions, + cardStyle = state.favoriteItems.toListItemCardStyle(index = index), modifier = Modifier .standardHorizontalMargin() - .padding(top = 12.dp, bottom = 16.dp) + .fillMaxWidth(), + ) + } + } + + if (state.shouldShowLocalHeader) { + item(key = "local_items_header") { + AuthenticatorExpandingHeader( + label = stringResource( + id = BitwardenString.local_codes, + state.itemList.size, + ), + isExpanded = isLocalHeaderExpanded, + onClick = { isLocalHeaderExpanded = !isLocalHeaderExpanded }, + onClickLabel = stringResource( + id = if (isLocalHeaderExpanded) { + BitwardenString.local_items_are_expanded_click_to_collapse + } else { + BitwardenString.local_items_are_collapsed_click_to_expand + }, + ), + modifier = Modifier + .fillMaxWidth() + .standardHorizontalMargin() .animateItem(), ) } - if (state.favoriteItems.isNotEmpty()) { - item(key = "favorites_header") { - BitwardenListHeaderText( - label = stringResource(id = BitwardenString.favorites), - supportingLabel = state.favoriteItems.count().toString(), + } + + if (isLocalHeaderExpanded) { + itemsIndexed( + items = state.itemList, + key = { _, it -> "local_item_${it.id}" }, + ) { index, it -> + VaultVerificationCodeItem( + authCode = it.authCode, + primaryLabel = it.title, + secondaryLabel = it.subtitle, + periodSeconds = it.periodSeconds, + timeLeftSeconds = it.timeLeftSeconds, + alertThresholdSeconds = it.alertThresholdSeconds, + startIcon = it.startIcon, + onItemClick = { onItemClick(it.authCode) }, + onDropdownMenuClick = { action -> + onDropdownMenuClick(action, it) + }, + showMoveToBitwarden = it.showMoveToBitwarden, + allowLongPress = it.allowLongPressActions, + cardStyle = state.itemList.toListItemCardStyle(index = index), + modifier = Modifier + .standardHorizontalMargin() + .fillMaxWidth() + .animateItem(), + ) + } + } + + when (state.sharedItems) { + is SharedCodesDisplayState.Codes -> { + state.sharedItems.sections.forEachIndexed { index, section -> + item(key = "sharedSection_${section.label}") { + AuthenticatorExpandingHeader( + label = section.label(), + isExpanded = section.isExpanded, + onClick = { + onSectionExpandedClick(section) + }, + onClickLabel = stringResource( + id = if (section.isExpanded) { + BitwardenString.items_expanded_click_to_collapse + } else { + BitwardenString.items_are_collapsed_click_to_expand + }, + ), + modifier = Modifier + .fillMaxWidth() + .standardHorizontalMargin() + .animateItem(), + ) + } + if (section.isExpanded) { + itemsIndexed( + items = section.codes, + key = { _, code -> "code_${code.id}" }, + ) { index, it -> + VaultVerificationCodeItem( + authCode = it.authCode, + primaryLabel = it.title, + secondaryLabel = it.subtitle, + periodSeconds = it.periodSeconds, + timeLeftSeconds = it.timeLeftSeconds, + alertThresholdSeconds = it.alertThresholdSeconds, + startIcon = it.startIcon, + onItemClick = { onItemClick(it.authCode) }, + onDropdownMenuClick = { action -> + onDropdownMenuClick(action, it) + }, + showMoveToBitwarden = it.showMoveToBitwarden, + allowLongPress = it.allowLongPressActions, + cardStyle = section.codes.toListItemCardStyle(index = index), + modifier = Modifier + .standardHorizontalMargin() + .fillMaxWidth() + .animateItem(), + ) + } + } + } + } + + SharedCodesDisplayState.Error -> { + item(key = "shared_codes_error") { + Text( + text = stringResource(BitwardenString.shared_codes_error), + color = BitwardenTheme.colorScheme.text.secondary, + style = BitwardenTheme.typography.bodySmall, modifier = Modifier - .fillMaxWidth() .standardHorizontalMargin() .padding(horizontal = 16.dp) .animateItem(), ) - Spacer(modifier = Modifier.height(height = 8.dp)) - } - - itemsIndexed( - items = state.favoriteItems, - key = { _, it -> "favorite_item_${it.id}" }, - ) { index, it -> - VaultVerificationCodeItem( - authCode = it.authCode, - primaryLabel = it.title, - secondaryLabel = it.subtitle, - periodSeconds = it.periodSeconds, - timeLeftSeconds = it.timeLeftSeconds, - alertThresholdSeconds = it.alertThresholdSeconds, - startIcon = it.startIcon, - onItemClick = { onItemClick(it.authCode) }, - onDropdownMenuClick = { action -> - onDropdownMenuClick(action, it) - }, - showMoveToBitwarden = it.showMoveToBitwarden, - allowLongPress = it.allowLongPressActions, - cardStyle = state.favoriteItems.toListItemCardStyle(index = index), - modifier = Modifier - .standardHorizontalMargin() - .fillMaxWidth(), - ) } } + } - if (state.shouldShowLocalHeader) { - item(key = "local_items_header") { - AuthenticatorExpandingHeader( - label = stringResource( - id = BitwardenString.local_codes, - state.itemList.size, - ), - isExpanded = isLocalHeaderExpanded, - onClick = { isLocalHeaderExpanded = !isLocalHeaderExpanded }, - onClickLabel = if (isLocalHeaderExpanded) { - stringResource( - BitwardenString.local_items_are_expanded_click_to_collapse, - ) - } else { - stringResource( - BitwardenString.local_items_are_collapsed_click_to_expand, - ) - }, - modifier = Modifier - .fillMaxWidth() - .standardHorizontalMargin() - .animateItem(), - ) - } - } - - if (isLocalHeaderExpanded) { - itemsIndexed( - items = state.itemList, - key = { _, it -> "local_item_${it.id}" }, - ) { index, it -> - VaultVerificationCodeItem( - authCode = it.authCode, - primaryLabel = it.title, - secondaryLabel = it.subtitle, - periodSeconds = it.periodSeconds, - timeLeftSeconds = it.timeLeftSeconds, - alertThresholdSeconds = it.alertThresholdSeconds, - startIcon = it.startIcon, - onItemClick = { onItemClick(it.authCode) }, - onDropdownMenuClick = { action -> - onDropdownMenuClick(action, it) - }, - showMoveToBitwarden = it.showMoveToBitwarden, - allowLongPress = it.allowLongPressActions, - cardStyle = state.itemList.toListItemCardStyle(index = index), - modifier = Modifier - .standardHorizontalMargin() - .fillMaxWidth() - .animateItem(), - ) - } - } - - when (state.sharedItems) { - is SharedCodesDisplayState.Codes -> { - state.sharedItems.sections.forEachIndexed { index, section -> - item(key = "sharedSection_${section.label}") { - AuthenticatorExpandingHeader( - label = section.label(), - isExpanded = section.isExpanded, - onClick = { - onSectionExpandedClick(section) - }, - onClickLabel = if (section.isExpanded) { - stringResource(BitwardenString.items_expanded_click_to_collapse) - } else { - stringResource( - BitwardenString.items_are_collapsed_click_to_expand, - ) - }, - modifier = Modifier - .fillMaxWidth() - .standardHorizontalMargin() - .animateItem(), - ) - } - if (section.isExpanded) { - itemsIndexed( - items = section.codes, - key = { _, code -> "code_${code.id}" }, - ) { index, it -> - VaultVerificationCodeItem( - authCode = it.authCode, - primaryLabel = it.title, - secondaryLabel = it.subtitle, - periodSeconds = it.periodSeconds, - timeLeftSeconds = it.timeLeftSeconds, - alertThresholdSeconds = it.alertThresholdSeconds, - startIcon = it.startIcon, - onItemClick = { onItemClick(it.authCode) }, - onDropdownMenuClick = { action -> - onDropdownMenuClick(action, it) - }, - showMoveToBitwarden = it.showMoveToBitwarden, - allowLongPress = it.allowLongPressActions, - cardStyle = section.codes.toListItemCardStyle(index = index), - modifier = Modifier - .standardHorizontalMargin() - .fillMaxWidth() - .animateItem(), - ) - } - } - } - } - - SharedCodesDisplayState.Error -> { - item(key = "shared_codes_error") { - Text( - text = stringResource(BitwardenString.shared_codes_error), - color = BitwardenTheme.colorScheme.text.secondary, - style = BitwardenTheme.typography.bodySmall, - modifier = Modifier - .standardHorizontalMargin() - .padding(horizontal = 16.dp) - .animateItem(), - ) - } - } - } - - // Add a spacer item to prevent the FAB from hiding verification codes at the - // bottom of the list - item { - Spacer(modifier = Modifier.height(height = 88.dp)) - Spacer(modifier = Modifier.navigationBarsPadding()) - } + // Add a spacer item to prevent the FAB from hiding verification codes at the + // bottom of the list + item { + Spacer(modifier = Modifier.height(height = 88.dp)) + Spacer(modifier = Modifier.navigationBarsPadding()) } } } @@ -601,147 +535,95 @@ private fun ItemListingContent( * Displays the item listing screen with no existing items. */ @Suppress("LongMethod") -@OptIn(ExperimentalMaterial3Api::class) @Composable fun EmptyItemListingContent( - modifier: Modifier = Modifier, actionCardState: ItemListingState.ActionCardState, appTheme: AppTheme, - scrollBehavior: TopAppBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior( - rememberTopAppBarState(), - ), onAddCodeClick: () -> Unit, - onScanQrCodeClick: () -> Unit, - onEnterSetupKeyClick: () -> Unit, onDownloadBitwardenClick: () -> Unit, onDismissDownloadBitwardenClick: () -> Unit, onSyncWithBitwardenClick: () -> Unit, onSyncLearnMoreClick: () -> Unit, onDismissSyncWithBitwardenClick: () -> Unit, + modifier: Modifier = Modifier, ) { - BitwardenScaffold( - modifier = Modifier + Column( + modifier = modifier .fillMaxSize() - .nestedScroll(scrollBehavior.nestedScrollConnection), - topBar = { - BitwardenTopAppBar( - title = stringResource(id = BitwardenString.verification_codes), - scrollBehavior = scrollBehavior, - navigationIcon = null, - ) - }, - floatingActionButton = { - BitwardenExpandableFloatingActionButton( - modifier = Modifier.testTag("AddItemButton"), - items = persistentListOf( - ItemListingExpandableFabAction.ScanQrCode( - label = BitwardenString.scan_a_qr_code.asText(), - icon = IconData.Local( - iconRes = BitwardenDrawable.ic_camera_small, - contentDescription = BitwardenString.scan_a_qr_code.asText(), - testTag = "ScanQRCodeButton", - ), - onScanQrCodeClick = onScanQrCodeClick, - ), - ItemListingExpandableFabAction.EnterSetupKey( - label = BitwardenString.enter_key_manually.asText(), - icon = IconData.Local( - iconRes = BitwardenDrawable.ic_lock_encrypted_small, - contentDescription = BitwardenString.enter_key_manually.asText(), - testTag = "EnterSetupKeyButton", - ), - onEnterSetupKeyClick = onEnterSetupKeyClick, - ), - ), - expandableFabIcon = ExpandableFabIcon( - icon = IconData.Local( - iconRes = BitwardenDrawable.ic_plus, - contentDescription = BitwardenString.add_item.asText(), - testTag = "AddItemButton", - ), - iconRotation = 45f, - ), - ) + .verticalScroll(rememberScrollState()), + verticalArrangement = when (actionCardState) { + ItemListingState.ActionCardState.None -> Arrangement.Center + ItemListingState.ActionCardState.DownloadBitwardenApp -> Arrangement.Top + ItemListingState.ActionCardState.SyncWithBitwarden -> Arrangement.Top }, ) { + ActionCard( + actionCardState = actionCardState, + onDownloadBitwardenClick = onDownloadBitwardenClick, + onDownloadBitwardenDismissClick = onDismissDownloadBitwardenClick, + onSyncWithBitwardenClick = onSyncWithBitwardenClick, + onSyncWithBitwardenDismissClick = onDismissSyncWithBitwardenClick, + onSyncLearnMoreClick = onSyncLearnMoreClick, + modifier = Modifier + .standardHorizontalMargin() + .padding(top = 12.dp, bottom = 16.dp), + ) + Column( modifier = modifier .fillMaxSize() - .verticalScroll(rememberScrollState()), - verticalArrangement = when (actionCardState) { - ItemListingState.ActionCardState.None -> Arrangement.Center - ItemListingState.ActionCardState.DownloadBitwardenApp -> Arrangement.Top - ItemListingState.ActionCardState.SyncWithBitwarden -> Arrangement.Top - }, + .standardHorizontalMargin(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, ) { - ActionCard( - actionCardState = actionCardState, - onDownloadBitwardenClick = onDownloadBitwardenClick, - onDownloadBitwardenDismissClick = onDismissDownloadBitwardenClick, - onSyncWithBitwardenClick = onSyncWithBitwardenClick, - onSyncWithBitwardenDismissClick = onDismissSyncWithBitwardenClick, - onSyncLearnMoreClick = onSyncLearnMoreClick, - modifier = Modifier - .standardHorizontalMargin() - .padding(top = 12.dp, bottom = 16.dp), + + Image( + modifier = Modifier.fillMaxWidth(), + painter = painterResource( + id = when (appTheme) { + AppTheme.DARK -> BitwardenDrawable.ic_empty_vault_dark + AppTheme.LIGHT -> BitwardenDrawable.ic_empty_vault_light + AppTheme.DEFAULT -> BitwardenDrawable.ic_empty_vault + }, + ), + contentDescription = stringResource( + id = BitwardenString.empty_item_list, + ), + contentScale = ContentScale.Fit, ) - Column( - modifier = modifier - .fillMaxSize() - .standardHorizontalMargin(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, - ) { + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = stringResource(id = BitwardenString.you_dont_have_items_to_display), + style = BitwardenTheme.typography.titleMedium, + ) - Image( - modifier = Modifier.fillMaxWidth(), - painter = painterResource( - id = when (appTheme) { - AppTheme.DARK -> BitwardenDrawable.ic_empty_vault_dark - AppTheme.LIGHT -> BitwardenDrawable.ic_empty_vault_light - AppTheme.DEFAULT -> BitwardenDrawable.ic_empty_vault - }, - ), - contentDescription = stringResource( - id = BitwardenString.empty_item_list, - ), - contentScale = ContentScale.Fit, - ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + textAlign = TextAlign.Center, + text = stringResource(id = BitwardenString.empty_item_list_instruction), + ) - Spacer(modifier = Modifier.height(16.dp)) - Text( - text = stringResource(id = BitwardenString.you_dont_have_items_to_display), - style = BitwardenTheme.typography.titleMedium, - ) + Spacer(modifier = Modifier.height(16.dp)) + BitwardenFilledButton( + modifier = Modifier + .testTag("AddCodeButton") + .fillMaxWidth(), + label = stringResource(BitwardenString.add_code), + onClick = onAddCodeClick, + ) - Spacer(modifier = Modifier.height(16.dp)) - Text( - textAlign = TextAlign.Center, - text = stringResource(id = BitwardenString.empty_item_list_instruction), - ) - - Spacer(modifier = Modifier.height(16.dp)) - BitwardenFilledButton( - modifier = Modifier - .testTag("AddCodeButton") - .fillMaxWidth(), - label = stringResource(BitwardenString.add_code), - onClick = onAddCodeClick, - ) - - Spacer(modifier = Modifier.height(height = 12.dp)) - Spacer(modifier = Modifier.navigationBarsPadding()) - } + Spacer(modifier = Modifier.height(height = 12.dp)) + Spacer(modifier = Modifier.navigationBarsPadding()) } } } @Composable private fun DownloadBitwardenActionCard( - modifier: Modifier = Modifier, onDismissClick: () -> Unit, onDownloadBitwardenClick: () -> Unit, + modifier: Modifier = Modifier, ) = BitwardenActionCard( modifier = modifier, cardSubtitle = stringResource(BitwardenString.download_bitwarden_card_message), @@ -761,10 +643,10 @@ private fun DownloadBitwardenActionCard( @Suppress("LongMethod") @Composable private fun SyncWithBitwardenActionCard( - modifier: Modifier = Modifier, onDismissClick: () -> Unit, onAppSettingsClick: () -> Unit, onLearnMoreClick: () -> Unit, + modifier: Modifier = Modifier, ) { Card( modifier = modifier, @@ -865,7 +747,6 @@ private fun ActionCard( } } -@OptIn(ExperimentalMaterial3Api::class) @Composable @Preview(showBackground = true) private fun EmptyListingContentPreview() { @@ -873,8 +754,6 @@ private fun EmptyListingContentPreview() { modifier = Modifier.padding(horizontal = 16.dp), appTheme = AppTheme.DEFAULT, onAddCodeClick = { }, - onScanQrCodeClick = { }, - onEnterSetupKeyClick = { }, actionCardState = ItemListingState.ActionCardState.DownloadBitwardenApp, onDownloadBitwardenClick = { }, onDismissDownloadBitwardenClick = { }, @@ -884,8 +763,6 @@ private fun EmptyListingContentPreview() { ) } -@Suppress("LongMethod") -@OptIn(ExperimentalMaterial3Api::class) @Composable @Preview(showBackground = true) private fun ContentPreview() { @@ -934,13 +811,6 @@ private fun ContentPreview() { ), ), ), - snackbarHostState = remember { SnackbarHostState() }, - scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior( - rememberTopAppBarState(), - ), - onNavigateToSearch = { }, - onScanQrCodeClick = { }, - onEnterSetupKeyClick = { }, onItemClick = { }, onDropdownMenuClick = { _, _ -> }, onDownloadBitwardenClick = { },