Enable TwoPaneRegistrationScaffold panes to scroll independently.

This commit is contained in:
jeffrey-signal 2026-06-03 06:54:05 -04:00 committed by Cody Henthorne
parent 8af7606e3f
commit f3a5bba3f2
11 changed files with 98 additions and 47 deletions

View File

@ -78,6 +78,7 @@ private fun OnePaneLayout(
modifier: Modifier = Modifier
) {
val scrollState = rememberScrollState()
OnePaneRegistrationScaffold(
modifier = modifier.fillMaxSize(),
params = params,
@ -129,7 +130,9 @@ private fun TwoPaneLayout(
onEvent: (EnterAepEvents) -> Unit,
modifier: Modifier = Modifier
) {
val scrollState = rememberScrollState()
val firstPaneScrollState = rememberScrollState()
val secondPaneScrollState = rememberScrollState()
TwoPaneRegistrationScaffold(
modifier = modifier.fillMaxSize(),
params = params,
@ -138,7 +141,7 @@ private fun TwoPaneLayout(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.verticalScroll(scrollState)
.verticalScroll(firstPaneScrollState)
.padding(paddingValues)
) {
Description()
@ -149,7 +152,7 @@ private fun TwoPaneLayout(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.verticalScroll(scrollState)
.verticalScroll(secondPaneScrollState)
.padding(paddingValues)
) {
RecoveryKeyTextField(state, onEvent)
@ -157,7 +160,7 @@ private fun TwoPaneLayout(
},
footer = {
RegistrationScaffold.FooterSurface(
isContentScrolledUnder = scrollState.canScrollForward
isContentScrolledUnder = firstPaneScrollState.canScrollForward || secondPaneScrollState.canScrollForward
) {
Row(
horizontalArrangement = Arrangement.End,

View File

@ -11,7 +11,10 @@ import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
@ -56,6 +59,8 @@ fun AllowNotificationsScreen(
@OptIn(ExperimentalPermissionsApi::class)
@Composable
private fun OnePane(params: RegistrationScaffold.Params.OnePane, permissionState: PermissionState, onProceed: () -> Unit) {
val scrollState = rememberScrollState()
OnePaneRegistrationScaffold(
params = params,
footer = {
@ -64,10 +69,12 @@ private fun OnePane(params: RegistrationScaffold.Params.OnePane, permissionState
onProceed = onProceed
)
}
) {
) { paddingValues ->
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(it)
modifier = Modifier
.verticalScroll(scrollState)
.padding(paddingValues)
) {
FirstPaneContent()
SecondPaneContent()
@ -78,20 +85,27 @@ private fun OnePane(params: RegistrationScaffold.Params.OnePane, permissionState
@OptIn(ExperimentalPermissionsApi::class)
@Composable
private fun TwoPane(params: RegistrationScaffold.Params.TwoPane, permissionState: PermissionState, onProceed: () -> Unit) {
val firstPaneScrollState = rememberScrollState()
val secondPaneScrollState = rememberScrollState()
TwoPaneRegistrationScaffold(
params = params,
firstPane = {
firstPane = { paddingValues ->
FirstPaneContent(
modifier = Modifier
.padding(it)
.weight(1f)
.fillMaxHeight()
.verticalScroll(firstPaneScrollState)
.padding(paddingValues)
)
},
secondPane = {
secondPane = { paddingValues ->
SecondPaneContent(
modifier = Modifier
.padding(it)
.weight(1f)
.fillMaxHeight()
.verticalScroll(secondPaneScrollState)
.padding(paddingValues)
)
},
footer = {

View File

@ -113,17 +113,18 @@ private fun OnePane(
state: LinkAccountScreenState,
onEvent: (LinkAccountScreenEvent) -> Unit
) {
val scrollState = rememberScrollState()
OnePaneRegistrationScaffold(
params = params,
footer = { OnePaneFooterContent(onEvent = onEvent) }
) {
val scroller = rememberScrollState()
) { paddingValues ->
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = spacedBy(64.dp),
modifier = Modifier
.padding(it)
.verticalScroll(scroller)
.padding(paddingValues)
.verticalScroll(scrollState)
) {
Title()
@ -142,21 +143,21 @@ private fun TwoPane(
) {
TwoPaneRegistrationScaffold(
params = params,
firstPane = {
firstPane = { paddingValues ->
FirstPaneContent(
onEvent = onEvent,
modifier = Modifier
.padding(it)
.padding(paddingValues)
.weight(1f)
)
},
secondPane = {
secondPane = { paddingValues ->
QrCodeContent(
state = state,
onEvent = onEvent,
modifier = Modifier
.weight(1f)
.padding(it)
.padding(paddingValues)
)
},
footer = { TwoPaneFooterContent(onEvent = onEvent) }

View File

@ -148,7 +148,9 @@ private fun TwoPaneLayout(
onCancel: () -> Unit,
modifier: Modifier
) {
val scrollState = rememberScrollState()
val firstPaneScrollState = rememberScrollState()
val secondPaneScrollState = rememberScrollState()
TwoPaneRegistrationScaffold(
modifier = modifier.fillMaxSize(),
params = params,
@ -157,7 +159,7 @@ private fun TwoPaneLayout(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.verticalScroll(scrollState)
.verticalScroll(firstPaneScrollState)
.padding(paddingValues)
) {
Description()
@ -168,7 +170,7 @@ private fun TwoPaneLayout(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.verticalScroll(scrollState)
.verticalScroll(secondPaneScrollState)
.padding(paddingValues)
) {
PassphraseTextField(

View File

@ -44,6 +44,7 @@ internal fun LocalBackupRestoreLayout(
when (val params = RegistrationScaffold.rememberLayoutParams()) {
is RegistrationScaffold.Params.OnePane -> {
val scrollState = rememberScrollState()
OnePaneRegistrationScaffold(
modifier = modifier.fillMaxSize(),
params = params,
@ -87,6 +88,7 @@ internal fun LocalBackupRestoreLayout(
is RegistrationScaffold.Params.TwoPane -> {
val firstPaneScrollState = rememberScrollState()
val secondPaneScrollState = rememberScrollState()
TwoPaneRegistrationScaffold(
modifier = modifier
.fillMaxSize()

View File

@ -10,9 +10,12 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
@ -68,13 +71,17 @@ fun MessageSyncScreen(
@Composable
private fun OnePane(params: RegistrationScaffold.Params.OnePane, state: MessageSyncScreenState, onEvent: (MessageSyncScreenEvent) -> Unit) {
val scrollState = rememberScrollState()
OnePaneRegistrationScaffold(
params = params,
footer = { FooterContent(params = params, onEvent = onEvent) }
) {
) { paddingValues ->
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(it)
modifier = Modifier
.verticalScroll(scrollState)
.padding(paddingValues)
) {
FirstPaneContent(state)
SecondPaneContent()
@ -84,21 +91,27 @@ private fun OnePane(params: RegistrationScaffold.Params.OnePane, state: MessageS
@Composable
private fun TwoPane(params: RegistrationScaffold.Params.TwoPane, state: MessageSyncScreenState, onEvent: (MessageSyncScreenEvent) -> Unit) {
val firstPaneScrollState = rememberScrollState()
val secondPaneScrollState = rememberScrollState()
TwoPaneRegistrationScaffold(
params = params,
firstPane = {
firstPane = { paddingValues ->
FirstPaneContent(
state = state,
modifier = Modifier
.padding(it)
.weight(1f)
.fillMaxHeight()
.verticalScroll(firstPaneScrollState)
.padding(paddingValues)
)
},
secondPane = {
secondPane = { paddingValues ->
SecondPaneContent(
modifier = Modifier
.padding(it)
.weight(1f)
.verticalScroll(secondPaneScrollState)
.padding(paddingValues)
)
},
footer = { FooterContent(params = params, onEvent = onEvent) }
@ -253,7 +266,9 @@ private fun Notice(modifier: Modifier, onEvent: (MessageSyncScreenEvent) -> Unit
textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.testTag(TestTags.MESSAGE_SYNC_LEARN_MORE_LINK).widthIn(max = 405.dp)
modifier = Modifier
.testTag(TestTags.MESSAGE_SYNC_LEARN_MORE_LINK)
.widthIn(max = 405.dp)
)
Spacer(modifier = Modifier.weight(1f))

View File

@ -113,7 +113,9 @@ private fun OnePaneLayout(
Text(
text = stringResource(id = R.string.GrantPermissionsFragment__allow_permissions),
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.fillMaxWidth().attachDebugLogHelper()
modifier = Modifier
.fillMaxWidth()
.attachDebugLogHelper()
)
Text(
@ -146,7 +148,8 @@ private fun TwoPaneLayout(
permissionsState: MultiplePermissionsState,
onProceed: () -> Unit
) {
val scrollState = rememberScrollState()
val firstPaneScrollState = rememberScrollState()
val secondPaneScrollState = rememberScrollState()
TwoPaneRegistrationScaffold(
modifier = modifier.fillMaxSize(),
@ -156,12 +159,15 @@ private fun TwoPaneLayout(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.verticalScroll(firstPaneScrollState)
.padding(paddingValues)
) {
Text(
text = stringResource(id = R.string.GrantPermissionsFragment__allow_permissions),
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.fillMaxWidth().attachDebugLogHelper()
modifier = Modifier
.fillMaxWidth()
.attachDebugLogHelper()
)
Text(
@ -177,7 +183,7 @@ private fun TwoPaneLayout(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.verticalScroll(scrollState)
.verticalScroll(secondPaneScrollState)
.padding(paddingValues)
) {
PermissionList(permissions)
@ -187,7 +193,7 @@ private fun TwoPaneLayout(
PermissionButtons(
onProceed = onProceed,
permissionsState = permissionsState,
showElevation = scrollState.canScrollForward,
showElevation = firstPaneScrollState.canScrollForward || secondPaneScrollState.canScrollForward,
modifier = Modifier.padding(params.footerPadding)
)
}

View File

@ -170,7 +170,8 @@ private fun TwoPaneLayout(
onEvent: (PinCreationScreenEvents) -> Unit,
modifier: Modifier = Modifier
) {
val scrollState = rememberScrollState()
val firstPaneScrollState = rememberScrollState()
val secondPaneScrollState = rememberScrollState()
TwoPaneRegistrationScaffold(
modifier = modifier.fillMaxSize(),
@ -180,6 +181,7 @@ private fun TwoPaneLayout(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.verticalScroll(firstPaneScrollState)
.padding(paddingValues)
) {
PinDescription(
@ -193,7 +195,7 @@ private fun TwoPaneLayout(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.verticalScroll(scrollState)
.verticalScroll(secondPaneScrollState)
.padding(paddingValues)
) {
PinInputField(
@ -219,7 +221,7 @@ private fun TwoPaneLayout(
NextButton(
params = params,
canSubmitPin = canSubmitPin,
showElevation = scrollState.canScrollForward,
showElevation = firstPaneScrollState.canScrollForward || secondPaneScrollState.canScrollForward,
onNext = { onEvent(PinCreationScreenEvents.PinSubmitted(pin)) }
)
}

View File

@ -175,7 +175,8 @@ private fun TwoPaneLayout(
onEvent: (PinEntryScreenEvents) -> Unit,
modifier: Modifier = Modifier
) {
val scrollState = rememberScrollState()
val firstPaneScrollState = rememberScrollState()
val secondPaneScrollState = rememberScrollState()
TwoPaneRegistrationScaffold(
modifier = modifier.fillMaxSize(),
@ -185,6 +186,7 @@ private fun TwoPaneLayout(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.verticalScroll(firstPaneScrollState)
.padding(paddingValues)
) {
PinDescription(
@ -201,7 +203,7 @@ private fun TwoPaneLayout(
) {
Column(
modifier = Modifier
.verticalScroll(scrollState)
.verticalScroll(secondPaneScrollState)
.padding(paddingValues)
) {
PinInputField(
@ -232,7 +234,7 @@ private fun TwoPaneLayout(
ContinueButton(
params = params,
canSubmitPin = canSubmitPin,
showElevation = scrollState.canScrollForward,
showElevation = firstPaneScrollState.canScrollForward || secondPaneScrollState.canScrollForward,
onContinue = { onEvent(PinEntryScreenEvents.PinEntered(pin)) }
)
}

View File

@ -122,7 +122,9 @@ private fun TwoPaneLayout(
onEvent: (ArchiveRestoreSelectionScreenEvents) -> Unit,
modifier: Modifier
) {
val scrollState = rememberScrollState()
val firstPaneScrollState = rememberScrollState()
val secondPaneScrollState = rememberScrollState()
TwoPaneRegistrationScaffold(
modifier = modifier
.fillMaxSize()
@ -132,7 +134,7 @@ private fun TwoPaneLayout(
Column(
modifier = Modifier
.weight(1f)
.verticalScroll(scrollState)
.verticalScroll(firstPaneScrollState)
.padding(paddingValues)
) {
Description()
@ -142,7 +144,7 @@ private fun TwoPaneLayout(
Column(
modifier = Modifier
.weight(1f)
.verticalScroll(scrollState)
.verticalScroll(secondPaneScrollState)
.padding(paddingValues)
) {
RestoreOptions(state, onEvent)
@ -150,7 +152,7 @@ private fun TwoPaneLayout(
},
footer = {
RegistrationScaffold.FooterSurface(
isContentScrolledUnder = scrollState.canScrollForward
isContentScrolledUnder = firstPaneScrollState.canScrollForward || secondPaneScrollState.canScrollForward
) {
if (state.showSkipButton) {
Row(

View File

@ -231,7 +231,9 @@ private fun TwoPaneLayout(
onEvent: (VerificationCodeScreenEvents) -> Unit,
onDigitsChanged: (List<String>) -> Unit
) {
val scrollState = rememberScrollState()
val firstPaneScrollState = rememberScrollState()
val secondPaneScrollState = rememberScrollState()
TwoPaneRegistrationScaffold(
modifier = Modifier
.fillMaxSize()
@ -241,7 +243,7 @@ private fun TwoPaneLayout(
Column(
modifier = Modifier
.weight(1f)
.verticalScroll(scrollState)
.verticalScroll(firstPaneScrollState)
.padding(paddingValues)
) {
Description(state, onEvent)
@ -251,7 +253,7 @@ private fun TwoPaneLayout(
Column(
modifier = Modifier
.weight(1f)
.verticalScroll(scrollState)
.verticalScroll(secondPaneScrollState)
.padding(paddingValues)
) {
CodeField(
@ -270,7 +272,7 @@ private fun TwoPaneLayout(
},
footer = {
RegistrationScaffold.FooterSurface(
isContentScrolledUnder = scrollState.canScrollForward
isContentScrolledUnder = firstPaneScrollState.canScrollForward || secondPaneScrollState.canScrollForward
) {
Row(
modifier = Modifier