mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-06-28 10:05:45 +01:00
Use TopAppBar on all RegV5 screens.
This commit is contained in:
committed by
Cody Henthorne
parent
2adf84a895
commit
8af7606e3f
+20
@@ -16,13 +16,18 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Surface
|
||||
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.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.SubcomposeLayout
|
||||
import androidx.compose.ui.platform.LocalResources
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -30,6 +35,8 @@ import androidx.compose.ui.unit.sp
|
||||
import org.signal.core.ui.WindowBreakpoint
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.getWindowSizeClass
|
||||
import org.signal.core.ui.isHeightCompact
|
||||
import org.signal.core.ui.rememberWindowBreakpoint
|
||||
|
||||
object RegistrationScaffold {
|
||||
@@ -132,6 +139,19 @@ object RegistrationScaffold {
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun rememberTopBarScrollBehavior(): TopAppBarScrollBehavior {
|
||||
val isHeightCompact = LocalResources.current.getWindowSizeClass().isHeightCompact
|
||||
val topAppBarState = rememberTopAppBarState()
|
||||
|
||||
return if (isHeightCompact) {
|
||||
TopAppBarDefaults.enterAlwaysScrollBehavior(state = topAppBarState)
|
||||
} else {
|
||||
TopAppBarDefaults.pinnedScrollBehavior(state = topAppBarState)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FooterSurface(
|
||||
isContentScrolledUnder: Boolean,
|
||||
|
||||
+34
-34
@@ -28,6 +28,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -56,6 +57,7 @@ import org.signal.core.ui.compose.Dividers
|
||||
import org.signal.core.ui.compose.IconButtons.IconButton
|
||||
import org.signal.core.ui.compose.LargeFontPreviews
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.compose.Scaffolds
|
||||
import org.signal.core.ui.compose.SignalIcons
|
||||
import org.signal.registration.R
|
||||
import org.signal.registration.screens.OnePaneRegistrationScaffold
|
||||
@@ -85,58 +87,40 @@ private fun OnePaneLayout(
|
||||
state: CountryCodeState,
|
||||
onEvent: (CountryCodePickerScreenEvents) -> Unit
|
||||
) {
|
||||
val topBarScrollBehavior = RegistrationScaffold.rememberTopBarScrollBehavior()
|
||||
|
||||
OnePaneRegistrationScaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
params = layoutParams,
|
||||
topBar = {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
IconButton(
|
||||
onClick = { onEvent(CountryCodePickerScreenEvents.Dismissed) }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = SignalIcons.X.imageVector,
|
||||
contentDescription = stringResource(R.string.CountryCodeSelectScreen__close)
|
||||
)
|
||||
}
|
||||
Text(
|
||||
stringResource(R.string.CountryCodeSelectScreen__your_country),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.attachDebugLogHelper()
|
||||
)
|
||||
}
|
||||
TopAppBar(
|
||||
scrollBehavior = topBarScrollBehavior,
|
||||
onCloseClick = { onEvent(CountryCodePickerScreenEvents.Dismissed) }
|
||||
)
|
||||
}
|
||||
) {
|
||||
CountryList(state, onEvent)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun TwoPaneLayout(
|
||||
params: RegistrationScaffold.Params.TwoPane,
|
||||
state: CountryCodeState,
|
||||
onEvent: (CountryCodePickerScreenEvents) -> Unit
|
||||
) {
|
||||
val topBarScrollBehavior = RegistrationScaffold.rememberTopBarScrollBehavior()
|
||||
|
||||
TwoPaneRegistrationScaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
topBar = {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
IconButton(
|
||||
onClick = { onEvent(CountryCodePickerScreenEvents.Dismissed) }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = SignalIcons.X.imageVector,
|
||||
contentDescription = stringResource(R.string.CountryCodeSelectScreen__close)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
params = params,
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
scrollBehavior = topBarScrollBehavior,
|
||||
onCloseClick = { onEvent(CountryCodePickerScreenEvents.Dismissed) }
|
||||
)
|
||||
},
|
||||
firstPane = { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@@ -146,7 +130,7 @@ private fun TwoPaneLayout(
|
||||
) {
|
||||
Text(
|
||||
stringResource(R.string.CountryCodeSelectScreen__your_country),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
modifier = Modifier.attachDebugLogHelper()
|
||||
)
|
||||
}
|
||||
@@ -164,6 +148,22 @@ private fun TwoPaneLayout(
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun TopAppBar(
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
onCloseClick: () -> Unit
|
||||
) {
|
||||
Scaffolds.DefaultTopAppBar(
|
||||
title = "",
|
||||
titleContent = { _, _ -> },
|
||||
onNavigationClick = onCloseClick,
|
||||
navigationIcon = SignalIcons.X.imageVector,
|
||||
navigationContentDescription = stringResource(R.string.CountryCodeSelectScreen__close),
|
||||
scrollBehavior = scrollBehavior
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CountryList(state: CountryCodeState, onEvent: (CountryCodePickerScreenEvents) -> Unit) {
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
+67
-55
@@ -24,11 +24,13 @@ import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -41,6 +43,7 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalResources
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -57,6 +60,7 @@ import org.signal.core.ui.compose.Dialogs
|
||||
import org.signal.core.ui.compose.DropdownMenus
|
||||
import org.signal.core.ui.compose.IconButtons.IconButton
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.compose.Scaffolds
|
||||
import org.signal.registration.R
|
||||
import org.signal.registration.screens.OnePaneRegistrationScaffold
|
||||
import org.signal.registration.screens.RegistrationScaffold
|
||||
@@ -64,6 +68,7 @@ import org.signal.registration.screens.TwoPaneRegistrationScaffold
|
||||
import org.signal.registration.screens.attachDebugLogHelper
|
||||
import org.signal.registration.screens.phonenumber.PhoneNumberEntryState.OneTimeEvent
|
||||
import org.signal.registration.test.TestTags
|
||||
import org.signal.core.ui.R as CoreR
|
||||
|
||||
/**
|
||||
* Phone number entry screen
|
||||
@@ -120,51 +125,7 @@ fun PhoneNumberScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TopbarMenu() {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.End
|
||||
) {
|
||||
Box {
|
||||
val menuController = remember { DropdownMenus.MenuController() }
|
||||
IconButton(
|
||||
onClick = { menuController.show() }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(org.signal.core.ui.R.drawable.symbol_more_vertical_24),
|
||||
contentDescription = stringResource(R.string.RegistrationActivity_open_menu)
|
||||
)
|
||||
}
|
||||
|
||||
DropdownMenus.Menu(
|
||||
controller = menuController,
|
||||
offsetX = 24.dp,
|
||||
offsetY = 0.dp
|
||||
) {
|
||||
DropdownMenus.Item(
|
||||
text = {
|
||||
Text(text = stringResource(R.string.RegistrationActivity_use_proxy))
|
||||
},
|
||||
onClick = {
|
||||
// TODO: Implement use proxy
|
||||
menuController.hide()
|
||||
}
|
||||
)
|
||||
DropdownMenus.Item(
|
||||
text = {
|
||||
Text(text = stringResource(R.string.RegistrationActivity_link_device))
|
||||
},
|
||||
onClick = {
|
||||
// TODO: Implement link device
|
||||
menuController.hide()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun OnePaneLayout(
|
||||
params: RegistrationScaffold.Params.OnePane,
|
||||
@@ -175,16 +136,16 @@ private fun OnePaneLayout(
|
||||
val selectedCountryEmoji = state.countryEmoji
|
||||
|
||||
val scrollState = rememberScrollState()
|
||||
val topBarScrollBehavior = RegistrationScaffold.rememberTopBarScrollBehavior()
|
||||
|
||||
OnePaneRegistrationScaffold(
|
||||
params = params,
|
||||
topBar = {
|
||||
TopbarMenu()
|
||||
},
|
||||
topBar = { TopAppBar(scrollBehavior = topBarScrollBehavior) },
|
||||
content = { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.nestedScroll(topBarScrollBehavior.nestedScrollConnection)
|
||||
.verticalScroll(scrollState)
|
||||
.padding(paddingValues)
|
||||
) {
|
||||
@@ -224,6 +185,7 @@ private fun OnePaneLayout(
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun TwoPaneLayout(
|
||||
params: RegistrationScaffold.Params.TwoPane,
|
||||
@@ -233,18 +195,19 @@ private fun TwoPaneLayout(
|
||||
val selectedCountry = state.countryName
|
||||
val selectedCountryEmoji = state.countryEmoji
|
||||
|
||||
val scrollState = rememberScrollState()
|
||||
val firstPaneScrollState = rememberScrollState()
|
||||
val secondPaneScrollState = rememberScrollState()
|
||||
val topBarScrollBehavior = RegistrationScaffold.rememberTopBarScrollBehavior()
|
||||
|
||||
TwoPaneRegistrationScaffold(
|
||||
params = params,
|
||||
topBar = {
|
||||
TopbarMenu()
|
||||
},
|
||||
topBar = { TopAppBar(scrollBehavior = topBarScrollBehavior) },
|
||||
firstPane = { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.verticalScroll(scrollState)
|
||||
.nestedScroll(topBarScrollBehavior.nestedScrollConnection)
|
||||
.verticalScroll(firstPaneScrollState)
|
||||
.padding(paddingValues)
|
||||
) {
|
||||
Description()
|
||||
@@ -254,7 +217,8 @@ private fun TwoPaneLayout(
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.verticalScroll(scrollState)
|
||||
.nestedScroll(topBarScrollBehavior.nestedScrollConnection)
|
||||
.verticalScroll(secondPaneScrollState)
|
||||
.padding(paddingValues)
|
||||
) {
|
||||
CountryPicker(
|
||||
@@ -281,7 +245,7 @@ private fun TwoPaneLayout(
|
||||
},
|
||||
footer = {
|
||||
RegistrationScaffold.FooterSurface(
|
||||
isContentScrolledUnder = scrollState.canScrollForward
|
||||
isContentScrolledUnder = firstPaneScrollState.canScrollForward || secondPaneScrollState.canScrollForward
|
||||
) {
|
||||
NextButton(state, onEvent)
|
||||
}
|
||||
@@ -289,6 +253,54 @@ private fun TwoPaneLayout(
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun TopAppBar(
|
||||
scrollBehavior: TopAppBarScrollBehavior
|
||||
) {
|
||||
Scaffolds.DefaultTopAppBar(
|
||||
title = "",
|
||||
titleContent = { _, _ -> },
|
||||
onNavigationClick = { },
|
||||
navigationIcon = null,
|
||||
scrollBehavior = scrollBehavior,
|
||||
actions = {
|
||||
val menuController = remember { DropdownMenus.MenuController() }
|
||||
|
||||
IconButton(
|
||||
onClick = { menuController.show() },
|
||||
modifier = Modifier.padding(horizontal = 8.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(CoreR.drawable.symbol_more_vertical_24),
|
||||
contentDescription = stringResource(R.string.RegistrationActivity_open_menu)
|
||||
)
|
||||
}
|
||||
|
||||
DropdownMenus.Menu(
|
||||
controller = menuController,
|
||||
offsetX = 24.dp,
|
||||
offsetY = 0.dp
|
||||
) {
|
||||
DropdownMenus.Item(
|
||||
text = { Text(text = stringResource(R.string.RegistrationActivity_use_proxy)) },
|
||||
onClick = {
|
||||
TODO("Handle use proxy")
|
||||
menuController.hide()
|
||||
}
|
||||
)
|
||||
DropdownMenus.Item(
|
||||
text = { Text(text = stringResource(R.string.RegistrationActivity_link_device)) },
|
||||
onClick = {
|
||||
TODO("Handle link device")
|
||||
menuController.hide()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Description() {
|
||||
Text(
|
||||
|
||||
Reference in New Issue
Block a user