mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 07:05:35 +03:00
Pin the segmented control to toolbar in AddSendScreen (#4093)
This commit is contained in:
parent
970a1e14cd
commit
8eb408b140
4 changed files with 190 additions and 161 deletions
|
@ -21,10 +21,12 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.bottomDivider
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.mirrorIfRtl
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.scrolledContainerBottomDivider
|
||||
import com.x8bit.bitwarden.ui.platform.components.appbar.color.bitwardenTopAppBarColors
|
||||
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenStandardIconButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.TopAppBarDividerStyle
|
||||
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
|
||||
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
|
||||
|
@ -47,6 +49,7 @@ fun BitwardenTopAppBar(
|
|||
navigationIconContentDescription: String,
|
||||
onNavigationIconClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
dividerStyle: TopAppBarDividerStyle = TopAppBarDividerStyle.ON_SCROLL,
|
||||
actions: @Composable RowScope.() -> Unit = { },
|
||||
) {
|
||||
BitwardenTopAppBar(
|
||||
|
@ -58,6 +61,7 @@ fun BitwardenTopAppBar(
|
|||
onNavigationIconClick = onNavigationIconClick,
|
||||
),
|
||||
modifier = modifier,
|
||||
dividerStyle = dividerStyle,
|
||||
actions = actions,
|
||||
)
|
||||
}
|
||||
|
@ -82,6 +86,7 @@ fun BitwardenTopAppBar(
|
|||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
navigationIcon: NavigationIcon?,
|
||||
modifier: Modifier = Modifier,
|
||||
dividerStyle: TopAppBarDividerStyle = TopAppBarDividerStyle.ON_SCROLL,
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
) {
|
||||
var titleTextHasOverflow by remember {
|
||||
|
@ -102,6 +107,24 @@ fun BitwardenTopAppBar(
|
|||
}
|
||||
}
|
||||
}
|
||||
val customModifier = modifier
|
||||
.testTag(tag = "HeaderBarComponent")
|
||||
.scrolledContainerBottomDivider(
|
||||
topAppBarScrollBehavior = scrollBehavior,
|
||||
enabled = when (dividerStyle) {
|
||||
TopAppBarDividerStyle.NONE -> false
|
||||
TopAppBarDividerStyle.STATIC -> false
|
||||
TopAppBarDividerStyle.ON_SCROLL -> true
|
||||
},
|
||||
)
|
||||
.bottomDivider(
|
||||
enabled = when (dividerStyle) {
|
||||
TopAppBarDividerStyle.NONE -> false
|
||||
TopAppBarDividerStyle.STATIC -> true
|
||||
TopAppBarDividerStyle.ON_SCROLL -> false
|
||||
},
|
||||
thickness = (0.5).dp,
|
||||
)
|
||||
|
||||
if (titleTextHasOverflow) {
|
||||
MediumTopAppBar(
|
||||
|
@ -120,9 +143,7 @@ fun BitwardenTopAppBar(
|
|||
modifier = Modifier.testTag(tag = "PageTitleLabel"),
|
||||
)
|
||||
},
|
||||
modifier = modifier
|
||||
.testTag(tag = "HeaderBarComponent")
|
||||
.scrolledContainerBottomDivider(topAppBarScrollBehavior = scrollBehavior),
|
||||
modifier = customModifier,
|
||||
actions = actions,
|
||||
)
|
||||
} else {
|
||||
|
@ -144,9 +165,7 @@ fun BitwardenTopAppBar(
|
|||
},
|
||||
)
|
||||
},
|
||||
modifier = modifier
|
||||
.testTag(tag = "HeaderBarComponent")
|
||||
.scrolledContainerBottomDivider(topAppBarScrollBehavior = scrollBehavior),
|
||||
modifier = customModifier,
|
||||
actions = actions,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -18,8 +18,10 @@ import androidx.compose.foundation.layout.width
|
|||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
|
@ -33,6 +35,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.scrolledContainerBottomDivider
|
||||
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenFilledTonalButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenTextButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.card.BitwardenInfoCalloutCard
|
||||
|
@ -52,10 +55,12 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
/**
|
||||
* Content view for the [AddSendScreen].
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
fun AddSendContent(
|
||||
state: AddSendState.ViewState.Content,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
policyDisablesSend: Boolean,
|
||||
policySendOptionsInEffect: Boolean,
|
||||
isAddMode: Boolean,
|
||||
|
@ -67,14 +72,12 @@ fun AddSendContent(
|
|||
val chooseFileCameraPermissionLauncher = permissionsManager.getLauncher { isGranted ->
|
||||
addSendHandlers.onChooseFileClick(isGranted)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
if (isAddMode && !isShared) {
|
||||
BitwardenSegmentedButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier
|
||||
.scrolledContainerBottomDivider(topAppBarScrollBehavior = scrollBehavior)
|
||||
.fillMaxWidth(),
|
||||
options = persistentListOf(
|
||||
SegmentedButtonState(
|
||||
text = stringResource(id = R.string.file),
|
||||
|
@ -92,171 +95,177 @@ fun AddSendContent(
|
|||
)
|
||||
}
|
||||
|
||||
if (policyDisablesSend) {
|
||||
BitwardenInfoCalloutCard(
|
||||
text = stringResource(id = R.string.send_disabled_warning),
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
if (policySendOptionsInEffect) {
|
||||
BitwardenInfoCalloutCard(
|
||||
text = stringResource(id = R.string.send_options_policy_in_effect),
|
||||
modifier = Modifier
|
||||
.testTag("SendOptionsPolicyInEffectLabel")
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
BitwardenTextField(
|
||||
modifier = Modifier
|
||||
.testTag("SendNameEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
label = stringResource(id = R.string.name),
|
||||
hint = stringResource(id = R.string.name_info),
|
||||
readOnly = policyDisablesSend,
|
||||
value = state.common.name,
|
||||
onValueChange = addSendHandlers.onNamChange,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
when (val type = state.selectedType) {
|
||||
is AddSendState.ViewState.Content.SendType.File -> {
|
||||
BitwardenListHeaderText(
|
||||
label = stringResource(id = R.string.file),
|
||||
Column(
|
||||
modifier = Modifier.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
if (policyDisablesSend) {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenInfoCalloutCard(
|
||||
text = stringResource(id = R.string.send_disabled_warning),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
if (isShared) {
|
||||
Text(
|
||||
text = type.name.orEmpty(),
|
||||
color = BitwardenTheme.colorScheme.text.primary,
|
||||
style = BitwardenTheme.typography.bodyMedium,
|
||||
}
|
||||
|
||||
if (policySendOptionsInEffect) {
|
||||
BitwardenInfoCalloutCard(
|
||||
text = stringResource(id = R.string.send_options_policy_in_effect),
|
||||
modifier = Modifier
|
||||
.testTag(tag = "SendOptionsPolicyInEffectLabel")
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
BitwardenTextField(
|
||||
modifier = Modifier
|
||||
.testTag(tag = "SendNameEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
label = stringResource(id = R.string.name),
|
||||
hint = stringResource(id = R.string.name_info),
|
||||
readOnly = policyDisablesSend,
|
||||
value = state.common.name,
|
||||
onValueChange = addSendHandlers.onNamChange,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
when (val type = state.selectedType) {
|
||||
is AddSendState.ViewState.Content.SendType.File -> {
|
||||
BitwardenListHeaderText(
|
||||
label = stringResource(id = R.string.file),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = stringResource(id = R.string.max_file_size),
|
||||
color = BitwardenTheme.colorScheme.text.secondary,
|
||||
style = BitwardenTheme.typography.bodySmall,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
} else if (isAddMode) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.testTag("SendCurrentFileNameLabel")
|
||||
.align(Alignment.CenterHorizontally),
|
||||
text = type.name ?: stringResource(id = R.string.no_file_chosen),
|
||||
color = BitwardenTheme.colorScheme.text.secondary,
|
||||
style = BitwardenTheme.typography.bodySmall,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenFilledTonalButton(
|
||||
label = stringResource(id = R.string.choose_file),
|
||||
onClick = {
|
||||
if (permissionsManager.checkPermission(Manifest.permission.CAMERA)) {
|
||||
addSendHandlers.onChooseFileClick(true)
|
||||
} else {
|
||||
chooseFileCameraPermissionLauncher.launch(
|
||||
Manifest.permission.CAMERA,
|
||||
)
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.testTag("SendChooseFileButton")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
text = stringResource(id = R.string.max_file_size),
|
||||
color = BitwardenTheme.colorScheme.text.secondary,
|
||||
style = BitwardenTheme.typography.bodySmall,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 32.dp),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = stringResource(id = R.string.type_file_info),
|
||||
color = BitwardenTheme.colorScheme.text.secondary,
|
||||
style = BitwardenTheme.typography.bodySmall,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
} else {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
) {
|
||||
if (isShared) {
|
||||
Text(
|
||||
text = type.name.orEmpty(),
|
||||
color = BitwardenTheme.colorScheme.text.primary,
|
||||
style = BitwardenTheme.typography.bodyLarge,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = type.displaySize.orEmpty(),
|
||||
color = BitwardenTheme.colorScheme.text.primary,
|
||||
style = BitwardenTheme.typography.bodyMedium,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = stringResource(id = R.string.max_file_size),
|
||||
color = BitwardenTheme.colorScheme.text.secondary,
|
||||
style = BitwardenTheme.typography.bodySmall,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
} else if (isAddMode) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.testTag(tag = "SendCurrentFileNameLabel")
|
||||
.align(Alignment.CenterHorizontally),
|
||||
text = type.name ?: stringResource(id = R.string.no_file_chosen),
|
||||
color = BitwardenTheme.colorScheme.text.secondary,
|
||||
style = BitwardenTheme.typography.bodySmall,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenFilledTonalButton(
|
||||
label = stringResource(id = R.string.choose_file),
|
||||
onClick = {
|
||||
@Suppress("MaxLineLength")
|
||||
if (permissionsManager.checkPermission(Manifest.permission.CAMERA)) {
|
||||
addSendHandlers.onChooseFileClick(true)
|
||||
} else {
|
||||
chooseFileCameraPermissionLauncher.launch(
|
||||
Manifest.permission.CAMERA,
|
||||
)
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.testTag(tag = "SendChooseFileButton")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
text = stringResource(id = R.string.max_file_size),
|
||||
color = BitwardenTheme.colorScheme.text.secondary,
|
||||
style = BitwardenTheme.typography.bodySmall,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 32.dp),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = stringResource(id = R.string.type_file_info),
|
||||
color = BitwardenTheme.colorScheme.text.secondary,
|
||||
style = BitwardenTheme.typography.bodySmall,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
} else {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
) {
|
||||
Text(
|
||||
text = type.name.orEmpty(),
|
||||
color = BitwardenTheme.colorScheme.text.primary,
|
||||
style = BitwardenTheme.typography.bodyLarge,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = type.displaySize.orEmpty(),
|
||||
color = BitwardenTheme.colorScheme.text.primary,
|
||||
style = BitwardenTheme.typography.bodyMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AddSendState.ViewState.Content.SendType.Text -> {
|
||||
BitwardenTextField(
|
||||
modifier = Modifier
|
||||
.testTag(tag = "SendTextContentEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
label = stringResource(id = R.string.text),
|
||||
hint = stringResource(id = R.string.type_text_info),
|
||||
readOnly = policyDisablesSend,
|
||||
value = type.input,
|
||||
singleLine = false,
|
||||
onValueChange = addSendHandlers.onTextChange,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
BitwardenWideSwitch(
|
||||
modifier = Modifier
|
||||
.testTag(tag = "SendHideTextByDefaultToggle")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
label = stringResource(id = R.string.hide_text_by_default),
|
||||
isChecked = type.isHideByDefaultChecked,
|
||||
onCheckedChange = addSendHandlers.onIsHideByDefaultToggle,
|
||||
readOnly = policyDisablesSend,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is AddSendState.ViewState.Content.SendType.Text -> {
|
||||
BitwardenTextField(
|
||||
modifier = Modifier
|
||||
.testTag("SendTextContentEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
label = stringResource(id = R.string.text),
|
||||
hint = stringResource(id = R.string.type_text_info),
|
||||
readOnly = policyDisablesSend,
|
||||
value = type.input,
|
||||
singleLine = false,
|
||||
onValueChange = addSendHandlers.onTextChange,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
BitwardenWideSwitch(
|
||||
modifier = Modifier
|
||||
.testTag("SendHideTextByDefaultToggle")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
label = stringResource(id = R.string.hide_text_by_default),
|
||||
isChecked = type.isHideByDefaultChecked,
|
||||
onCheckedChange = addSendHandlers.onIsHideByDefaultToggle,
|
||||
readOnly = policyDisablesSend,
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
AddSendOptions(
|
||||
state = state,
|
||||
sendRestrictionPolicy = policyDisablesSend,
|
||||
isAddMode = isAddMode,
|
||||
addSendHandlers = addSendHandlers,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Spacer(modifier = Modifier.navigationBarsPadding())
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
AddSendOptions(
|
||||
state = state,
|
||||
sendRestrictionPolicy = policyDisablesSend,
|
||||
isAddMode = isAddMode,
|
||||
addSendHandlers = addSendHandlers,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Spacer(modifier = Modifier.navigationBarsPadding())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog
|
|||
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenLoadingDialog
|
||||
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
|
||||
import com.x8bit.bitwarden.ui.platform.components.dialog.LoadingDialogState
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.TopAppBarDividerStyle
|
||||
import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
|
||||
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
|
||||
import com.x8bit.bitwarden.ui.platform.composition.LocalExitManager
|
||||
|
@ -137,6 +138,7 @@ fun AddSendScreen(
|
|||
},
|
||||
)
|
||||
.takeUnless { state.isShared },
|
||||
dividerStyle = TopAppBarDividerStyle.NONE,
|
||||
scrollBehavior = scrollBehavior,
|
||||
actions = {
|
||||
BitwardenTextButton(
|
||||
|
@ -194,6 +196,7 @@ fun AddSendScreen(
|
|||
when (val viewState = state.viewState) {
|
||||
is AddSendState.ViewState.Content -> AddSendContent(
|
||||
state = viewState,
|
||||
scrollBehavior = scrollBehavior,
|
||||
policyDisablesSend = state.policyDisablesSend,
|
||||
policySendOptionsInEffect = state.shouldDisplayPolicyWarning,
|
||||
isAddMode = state.isAddMode,
|
||||
|
|
|
@ -376,12 +376,10 @@ class AddSendScreenTest : BaseComposeTest() {
|
|||
composeTestRule
|
||||
.onAllNodesWithText("File")
|
||||
.filterToOne(!isEditableText)
|
||||
.performScrollTo()
|
||||
.assertIsDisplayed()
|
||||
composeTestRule
|
||||
.onAllNodesWithText("Text")
|
||||
.filterToOne(!isEditableText)
|
||||
.performScrollTo()
|
||||
.assertIsDisplayed()
|
||||
|
||||
mutableStateFlow.update {
|
||||
|
|
Loading…
Reference in a new issue