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.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.x8bit.bitwarden.R
|
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.mirrorIfRtl
|
||||||
import com.x8bit.bitwarden.ui.platform.base.util.scrolledContainerBottomDivider
|
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.appbar.color.bitwardenTopAppBarColors
|
||||||
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenStandardIconButton
|
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.components.util.rememberVectorPainter
|
||||||
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
||||||
|
|
||||||
|
@ -47,6 +49,7 @@ fun BitwardenTopAppBar(
|
||||||
navigationIconContentDescription: String,
|
navigationIconContentDescription: String,
|
||||||
onNavigationIconClick: () -> Unit,
|
onNavigationIconClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
dividerStyle: TopAppBarDividerStyle = TopAppBarDividerStyle.ON_SCROLL,
|
||||||
actions: @Composable RowScope.() -> Unit = { },
|
actions: @Composable RowScope.() -> Unit = { },
|
||||||
) {
|
) {
|
||||||
BitwardenTopAppBar(
|
BitwardenTopAppBar(
|
||||||
|
@ -58,6 +61,7 @@ fun BitwardenTopAppBar(
|
||||||
onNavigationIconClick = onNavigationIconClick,
|
onNavigationIconClick = onNavigationIconClick,
|
||||||
),
|
),
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
dividerStyle = dividerStyle,
|
||||||
actions = actions,
|
actions = actions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -82,6 +86,7 @@ fun BitwardenTopAppBar(
|
||||||
scrollBehavior: TopAppBarScrollBehavior,
|
scrollBehavior: TopAppBarScrollBehavior,
|
||||||
navigationIcon: NavigationIcon?,
|
navigationIcon: NavigationIcon?,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
dividerStyle: TopAppBarDividerStyle = TopAppBarDividerStyle.ON_SCROLL,
|
||||||
actions: @Composable RowScope.() -> Unit = {},
|
actions: @Composable RowScope.() -> Unit = {},
|
||||||
) {
|
) {
|
||||||
var titleTextHasOverflow by remember {
|
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) {
|
if (titleTextHasOverflow) {
|
||||||
MediumTopAppBar(
|
MediumTopAppBar(
|
||||||
|
@ -120,9 +143,7 @@ fun BitwardenTopAppBar(
|
||||||
modifier = Modifier.testTag(tag = "PageTitleLabel"),
|
modifier = Modifier.testTag(tag = "PageTitleLabel"),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = modifier
|
modifier = customModifier,
|
||||||
.testTag(tag = "HeaderBarComponent")
|
|
||||||
.scrolledContainerBottomDivider(topAppBarScrollBehavior = scrollBehavior),
|
|
||||||
actions = actions,
|
actions = actions,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -144,9 +165,7 @@ fun BitwardenTopAppBar(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = modifier
|
modifier = customModifier,
|
||||||
.testTag(tag = "HeaderBarComponent")
|
|
||||||
.scrolledContainerBottomDivider(topAppBarScrollBehavior = scrollBehavior),
|
|
||||||
actions = actions,
|
actions = actions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,10 @@ import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.layout.wrapContentWidth
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
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.semantics.semantics
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.x8bit.bitwarden.R
|
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.BitwardenFilledTonalButton
|
||||||
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenTextButton
|
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenTextButton
|
||||||
import com.x8bit.bitwarden.ui.platform.components.card.BitwardenInfoCalloutCard
|
import com.x8bit.bitwarden.ui.platform.components.card.BitwardenInfoCalloutCard
|
||||||
|
@ -52,10 +55,12 @@ import kotlinx.collections.immutable.persistentListOf
|
||||||
/**
|
/**
|
||||||
* Content view for the [AddSendScreen].
|
* Content view for the [AddSendScreen].
|
||||||
*/
|
*/
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Suppress("LongMethod")
|
@Suppress("LongMethod")
|
||||||
@Composable
|
@Composable
|
||||||
fun AddSendContent(
|
fun AddSendContent(
|
||||||
state: AddSendState.ViewState.Content,
|
state: AddSendState.ViewState.Content,
|
||||||
|
scrollBehavior: TopAppBarScrollBehavior,
|
||||||
policyDisablesSend: Boolean,
|
policyDisablesSend: Boolean,
|
||||||
policySendOptionsInEffect: Boolean,
|
policySendOptionsInEffect: Boolean,
|
||||||
isAddMode: Boolean,
|
isAddMode: Boolean,
|
||||||
|
@ -67,14 +72,12 @@ fun AddSendContent(
|
||||||
val chooseFileCameraPermissionLauncher = permissionsManager.getLauncher { isGranted ->
|
val chooseFileCameraPermissionLauncher = permissionsManager.getLauncher { isGranted ->
|
||||||
addSendHandlers.onChooseFileClick(isGranted)
|
addSendHandlers.onChooseFileClick(isGranted)
|
||||||
}
|
}
|
||||||
|
Column(modifier = modifier) {
|
||||||
Column(
|
|
||||||
modifier = modifier
|
|
||||||
.verticalScroll(rememberScrollState()),
|
|
||||||
) {
|
|
||||||
if (isAddMode && !isShared) {
|
if (isAddMode && !isShared) {
|
||||||
BitwardenSegmentedButton(
|
BitwardenSegmentedButton(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier
|
||||||
|
.scrolledContainerBottomDivider(topAppBarScrollBehavior = scrollBehavior)
|
||||||
|
.fillMaxWidth(),
|
||||||
options = persistentListOf(
|
options = persistentListOf(
|
||||||
SegmentedButtonState(
|
SegmentedButtonState(
|
||||||
text = stringResource(id = R.string.file),
|
text = stringResource(id = R.string.file),
|
||||||
|
@ -92,7 +95,11 @@ fun AddSendContent(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.verticalScroll(rememberScrollState()),
|
||||||
|
) {
|
||||||
if (policyDisablesSend) {
|
if (policyDisablesSend) {
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
BitwardenInfoCalloutCard(
|
BitwardenInfoCalloutCard(
|
||||||
text = stringResource(id = R.string.send_disabled_warning),
|
text = stringResource(id = R.string.send_disabled_warning),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -106,7 +113,7 @@ fun AddSendContent(
|
||||||
BitwardenInfoCalloutCard(
|
BitwardenInfoCalloutCard(
|
||||||
text = stringResource(id = R.string.send_options_policy_in_effect),
|
text = stringResource(id = R.string.send_options_policy_in_effect),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.testTag("SendOptionsPolicyInEffectLabel")
|
.testTag(tag = "SendOptionsPolicyInEffectLabel")
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
@ -116,7 +123,7 @@ fun AddSendContent(
|
||||||
|
|
||||||
BitwardenTextField(
|
BitwardenTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.testTag("SendNameEntry")
|
.testTag(tag = "SendNameEntry")
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
label = stringResource(id = R.string.name),
|
label = stringResource(id = R.string.name),
|
||||||
|
@ -157,7 +164,7 @@ fun AddSendContent(
|
||||||
} else if (isAddMode) {
|
} else if (isAddMode) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.testTag("SendCurrentFileNameLabel")
|
.testTag(tag = "SendCurrentFileNameLabel")
|
||||||
.align(Alignment.CenterHorizontally),
|
.align(Alignment.CenterHorizontally),
|
||||||
text = type.name ?: stringResource(id = R.string.no_file_chosen),
|
text = type.name ?: stringResource(id = R.string.no_file_chosen),
|
||||||
color = BitwardenTheme.colorScheme.text.secondary,
|
color = BitwardenTheme.colorScheme.text.secondary,
|
||||||
|
@ -167,6 +174,7 @@ fun AddSendContent(
|
||||||
BitwardenFilledTonalButton(
|
BitwardenFilledTonalButton(
|
||||||
label = stringResource(id = R.string.choose_file),
|
label = stringResource(id = R.string.choose_file),
|
||||||
onClick = {
|
onClick = {
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
if (permissionsManager.checkPermission(Manifest.permission.CAMERA)) {
|
if (permissionsManager.checkPermission(Manifest.permission.CAMERA)) {
|
||||||
addSendHandlers.onChooseFileClick(true)
|
addSendHandlers.onChooseFileClick(true)
|
||||||
} else {
|
} else {
|
||||||
|
@ -176,7 +184,7 @@ fun AddSendContent(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.testTag("SendChooseFileButton")
|
.testTag(tag = "SendChooseFileButton")
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
)
|
)
|
||||||
|
@ -223,7 +231,7 @@ fun AddSendContent(
|
||||||
is AddSendState.ViewState.Content.SendType.Text -> {
|
is AddSendState.ViewState.Content.SendType.Text -> {
|
||||||
BitwardenTextField(
|
BitwardenTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.testTag("SendTextContentEntry")
|
.testTag(tag = "SendTextContentEntry")
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
label = stringResource(id = R.string.text),
|
label = stringResource(id = R.string.text),
|
||||||
|
@ -236,7 +244,7 @@ fun AddSendContent(
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
BitwardenWideSwitch(
|
BitwardenWideSwitch(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.testTag("SendHideTextByDefaultToggle")
|
.testTag(tag = "SendHideTextByDefaultToggle")
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
label = stringResource(id = R.string.hide_text_by_default),
|
label = stringResource(id = R.string.hide_text_by_default),
|
||||||
|
@ -259,6 +267,7 @@ fun AddSendContent(
|
||||||
Spacer(modifier = Modifier.navigationBarsPadding())
|
Spacer(modifier = Modifier.navigationBarsPadding())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays a collapsable set of new send options.
|
* Displays a collapsable set of new send options.
|
||||||
|
|
|
@ -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.BitwardenLoadingDialog
|
||||||
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
|
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.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.scaffold.BitwardenScaffold
|
||||||
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
|
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
|
||||||
import com.x8bit.bitwarden.ui.platform.composition.LocalExitManager
|
import com.x8bit.bitwarden.ui.platform.composition.LocalExitManager
|
||||||
|
@ -137,6 +138,7 @@ fun AddSendScreen(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.takeUnless { state.isShared },
|
.takeUnless { state.isShared },
|
||||||
|
dividerStyle = TopAppBarDividerStyle.NONE,
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
actions = {
|
actions = {
|
||||||
BitwardenTextButton(
|
BitwardenTextButton(
|
||||||
|
@ -194,6 +196,7 @@ fun AddSendScreen(
|
||||||
when (val viewState = state.viewState) {
|
when (val viewState = state.viewState) {
|
||||||
is AddSendState.ViewState.Content -> AddSendContent(
|
is AddSendState.ViewState.Content -> AddSendContent(
|
||||||
state = viewState,
|
state = viewState,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
policyDisablesSend = state.policyDisablesSend,
|
policyDisablesSend = state.policyDisablesSend,
|
||||||
policySendOptionsInEffect = state.shouldDisplayPolicyWarning,
|
policySendOptionsInEffect = state.shouldDisplayPolicyWarning,
|
||||||
isAddMode = state.isAddMode,
|
isAddMode = state.isAddMode,
|
||||||
|
|
|
@ -376,12 +376,10 @@ class AddSendScreenTest : BaseComposeTest() {
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onAllNodesWithText("File")
|
.onAllNodesWithText("File")
|
||||||
.filterToOne(!isEditableText)
|
.filterToOne(!isEditableText)
|
||||||
.performScrollTo()
|
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onAllNodesWithText("Text")
|
.onAllNodesWithText("Text")
|
||||||
.filterToOne(!isEditableText)
|
.filterToOne(!isEditableText)
|
||||||
.performScrollTo()
|
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
|
|
Loading…
Reference in a new issue