Refactor BitwardenOverflowTopAppBar for better re-use (#156)

This commit is contained in:
joshua-livefront 2023-10-24 15:54:11 -04:00 committed by Álison Fernandes
parent 8864315342
commit fe0fae4496
5 changed files with 47 additions and 137 deletions

View file

@ -62,8 +62,9 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog
import com.x8bit.bitwarden.ui.platform.components.BitwardenLoadingDialog
import com.x8bit.bitwarden.ui.platform.components.BitwardenPasswordField
import com.x8bit.bitwarden.ui.platform.components.BitwardenSwitch
import com.x8bit.bitwarden.ui.platform.components.BitwardenTextButtonTopAppBar
import com.x8bit.bitwarden.ui.platform.components.BitwardenTextButton
import com.x8bit.bitwarden.ui.platform.components.BitwardenTextField
import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar
import com.x8bit.bitwarden.ui.platform.components.BitwardenTwoButtonDialog
import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState
import com.x8bit.bitwarden.ui.platform.theme.clickableSpanStyle
@ -157,18 +158,21 @@ fun CreateAccountScreen(
.background(MaterialTheme.colorScheme.surface)
.verticalScroll(rememberScrollState()),
) {
BitwardenTextButtonTopAppBar(
BitwardenTopAppBar(
title = stringResource(id = R.string.create_account),
navigationIcon = painterResource(id = R.drawable.ic_close),
navigationIconContentDescription = stringResource(id = R.string.close),
onNavigationIconClick = remember(viewModel) {
{ viewModel.trySendAction(CloseClick) }
},
buttonText = stringResource(id = R.string.submit),
onButtonClick = remember(viewModel) {
{ viewModel.trySendAction(SubmitClick) }
actions = {
BitwardenTextButton(
label = stringResource(id = R.string.submit),
onClick = remember(viewModel) {
{ viewModel.trySendAction(SubmitClick) }
},
)
},
isButtonEnabled = true,
)
Spacer(modifier = Modifier.height(16.dp))
BitwardenTextField(

View file

@ -31,8 +31,9 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog
import com.x8bit.bitwarden.ui.platform.components.BitwardenFilledButton
import com.x8bit.bitwarden.ui.platform.components.BitwardenLoadingDialog
import com.x8bit.bitwarden.ui.platform.components.BitwardenOutlinedButtonWithIcon
import com.x8bit.bitwarden.ui.platform.components.BitwardenOverflowTopAppBar
import com.x8bit.bitwarden.ui.platform.components.BitwardenOverflowActionItem
import com.x8bit.bitwarden.ui.platform.components.BitwardenPasswordField
import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar
/**
* The top level composable for the Login screen.
@ -74,20 +75,24 @@ fun LoginScreen(
visibilityState = state.errorDialogState,
onDismissRequest = { viewModel.trySendAction(LoginAction.ErrorDialogDismiss) },
)
BitwardenOverflowTopAppBar(
BitwardenTopAppBar(
title = stringResource(id = R.string.app_name),
navigationIcon = painterResource(id = R.drawable.ic_close),
navigationIconContentDescription = stringResource(id = R.string.close),
onNavigationIconClick = remember(viewModel) {
{ viewModel.trySendAction(LoginAction.CloseButtonClick) }
},
dropdownMenuItemContent = {
DropdownMenuItem(
text = {
Text(text = stringResource(id = R.string.get_password_hint))
},
onClick = remember(viewModel) {
{ viewModel.trySendAction(LoginAction.MasterPasswordHintClick) }
actions = {
BitwardenOverflowActionItem(
dropdownMenuItemContent = {
DropdownMenuItem(
text = {
Text(text = stringResource(id = R.string.get_password_hint))
},
onClick = remember(viewModel) {
{ viewModel.trySendAction(LoginAction.MasterPasswordHintClick) }
},
)
},
)
},

View file

@ -1,96 +0,0 @@
package com.x8bit.bitwarden.ui.platform.components
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
/**
* Represents a Bitwarden-styled [TopAppBar] that assumes the following components:
*
* - a single navigation control in the upper-left defined by [navigationIcon],
* [navigationIconContentDescription], and [onNavigationIconClick].
* - a [title] in the middle.
* - a single overflow menu in the right with contents defined by the [dropdownMenuItemContent]. It
* is strongly recommended that this content be a stack of [DropdownMenuItem].
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BitwardenOverflowTopAppBar(
title: String,
navigationIcon: Painter,
navigationIconContentDescription: String,
onNavigationIconClick: () -> Unit,
dropdownMenuItemContent: @Composable ColumnScope.() -> Unit,
) {
var isOverflowMenuVisible by remember { mutableStateOf(false) }
TopAppBar(
navigationIcon = {
IconButton(
onClick = { onNavigationIconClick() },
) {
Icon(
painter = navigationIcon,
contentDescription = navigationIconContentDescription,
tint = MaterialTheme.colorScheme.onSurface,
)
}
},
title = {
Text(
text = title,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onSurface,
)
},
actions = {
Box {
IconButton(
onClick = { isOverflowMenuVisible = !isOverflowMenuVisible },
) {
Icon(
painter = painterResource(id = R.drawable.ic_more),
contentDescription = stringResource(id = R.string.more),
tint = MaterialTheme.colorScheme.onSurface,
)
}
DropdownMenu(
expanded = isOverflowMenuVisible,
onDismissRequest = { isOverflowMenuVisible = false },
content = dropdownMenuItemContent,
)
}
},
)
}
@Preview
@Composable
private fun BitwardenOverflowTopAppBar_preview() {
BitwardenTheme {
BitwardenOverflowTopAppBar(
title = "Title",
navigationIcon = painterResource(id = R.drawable.ic_close),
navigationIconContentDescription = stringResource(id = R.string.close),
onNavigationIconClick = {},
dropdownMenuItemContent = {},
)
}
}

View file

@ -1,5 +1,6 @@
package com.x8bit.bitwarden.ui.platform.components
import androidx.compose.foundation.layout.RowScope
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@ -12,6 +13,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
/**
* Represents a Bitwarden styled [TopAppBar] that assumes the following components:
@ -19,19 +21,18 @@ import com.x8bit.bitwarden.R
* - a single navigation control in the upper-left defined by [navigationIcon],
* [navigationIconContentDescription], and [onNavigationIconClick].
* - a [title] in the middle.
* - a [BitwardenTextButton] on the right that will display [buttonText] and call [onButtonClick]
* when clicked and [isButtonEnabled] is true.
* - a [actions] lambda containing the set of actions (usually icons or similar) to display
* in the app bar's trailing side. This lambda extends [RowScope], allowing flexibility in
* defining the layout of the actions.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BitwardenTextButtonTopAppBar(
fun BitwardenTopAppBar(
title: String,
navigationIcon: Painter,
navigationIconContentDescription: String,
onNavigationIconClick: () -> Unit,
buttonText: String,
onButtonClick: () -> Unit,
isButtonEnabled: Boolean,
actions: @Composable RowScope.() -> Unit = {},
) {
TopAppBar(
navigationIcon = {
@ -52,26 +53,19 @@ fun BitwardenTextButtonTopAppBar(
color = MaterialTheme.colorScheme.onSurface,
)
},
actions = {
BitwardenTextButton(
label = buttonText,
onClick = onButtonClick,
isEnabled = isButtonEnabled,
)
},
actions = actions,
)
}
@Preview
@Composable
private fun BitwardenTextButtonTopAppBar_preview() {
BitwardenTextButtonTopAppBar(
title = "Title",
navigationIcon = painterResource(id = R.drawable.ic_close),
navigationIconContentDescription = stringResource(id = R.string.close),
onNavigationIconClick = {},
buttonText = "Button",
onButtonClick = {},
isButtonEnabled = true,
)
private fun BitwardenTopAppBar_preview() {
BitwardenTheme {
BitwardenTopAppBar(
title = "Title",
navigationIcon = painterResource(id = R.drawable.ic_close),
navigationIconContentDescription = stringResource(id = R.string.close),
onNavigationIconClick = {},
)
}
}

View file

@ -23,7 +23,8 @@ import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
import com.x8bit.bitwarden.ui.platform.base.util.Text
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.components.BitwardenOverflowTopAppBar
import com.x8bit.bitwarden.ui.platform.components.BitwardenOverflowActionItem
import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar
/**
* Displays the account security screen.
@ -43,14 +44,16 @@ fun AccountSecurityScreen(
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.surface),
) {
BitwardenOverflowTopAppBar(
BitwardenTopAppBar(
title = stringResource(id = R.string.account),
navigationIcon = painterResource(id = R.drawable.ic_back),
navigationIconContentDescription = stringResource(id = R.string.back),
onNavigationIconClick = remember(viewModel) {
{ viewModel.trySendAction(AccountSecurityAction.BackClick) }
},
dropdownMenuItemContent = {},
actions = {
BitwardenOverflowActionItem()
},
)
Spacer(Modifier.height(8.dp))
AccountSecurityRow(