Skip to content

Commit

Permalink
Fix settings page back transition on COMPACT, close #1636
Browse files Browse the repository at this point in the history
  • Loading branch information
Him188 committed Feb 14, 2025
1 parent e2ae527 commit 45c4d1f
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@ data class ListDetailLayoutParameters(
* 是否为单页模式, 即整个屏幕上只会同时出现一个 pane. 通常在一个 COMPACT 设备上.
*/
val isSinglePane: Boolean,
/**
* 在 list pane 中高亮选中的 item.
*/
val highlightSelectedItem: Boolean = !isSinglePane,
) {
companion object {
@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
Expand Down Expand Up @@ -111,18 +112,40 @@ fun SettingsScreen(
windowInsets: WindowInsets = AniWindowInsets.forPageContent(),
navigationIcon: @Composable () -> Unit = {},
) {
val navigator: ThreePaneScaffoldNavigator<SettingsTab> = rememberListDetailPaneScaffoldNavigator(
var lastSelectedTab by remember {
mutableStateOf(initialTab)
}
val navigator: ThreePaneScaffoldNavigator<Nothing?> = rememberListDetailPaneScaffoldNavigator(
initialDestinationHistory = buildList {
add(ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.List))
if (initialTab != null) {
add(ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.Detail, initialTab))
add(ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.Detail))
}
},
)
val layoutParameters = ListDetailLayoutParameters.calculate(navigator.scaffoldDirective)
val coroutineScope = rememberCoroutineScope()

SettingsPageLayout(
navigator,
// TODO: 2025/2/14 We should have a SettingsNavController or so to control the tab state
{ lastSelectedTab },
onSelectedTab = { tab ->
coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
navigator.navigateTo(ListDetailPaneScaffoldRole.Detail)
lastSelectedTab = tab
}
},
onClickBackOnListPage = {
coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
navigator.navigateBack()
}
},
onClickBackOnDetailPage = {
coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
navigator.navigateBack(BackNavigationBehavior.PopUntilScaffoldValueChange)
}
},
navItems = {
Title("应用与界面", paddingTop = 0.dp)
Item(SettingsTab.APPEARANCE)
Expand Down Expand Up @@ -213,7 +236,11 @@ fun SettingsScreen(

@Composable
internal fun SettingsPageLayout(
navigator: ThreePaneScaffoldNavigator<SettingsTab>,
navigator: ThreePaneScaffoldNavigator<Nothing?>,
currentTab: () -> SettingsTab?,
onSelectedTab: (SettingsTab) -> Unit,
onClickBackOnListPage: () -> Unit,
onClickBackOnDetailPage: () -> Unit,
navItems: @Composable (SettingsDrawerScope.() -> Unit),
tabContent: @Composable PaneScope.(currentTab: SettingsTab?) -> Unit,
modifier: Modifier = Modifier,
Expand All @@ -224,8 +251,6 @@ internal fun SettingsPageLayout(
) = Surface(color = containerColor) {
val layoutParametersState by rememberUpdatedState(layoutParameters)

val coroutineScope = rememberCoroutineScope()

@Stable
fun SettingsTab?.orDefault(): SettingsTab? {
return if (layoutParametersState.isSinglePane) {
Expand All @@ -237,12 +262,6 @@ internal fun SettingsPageLayout(
}
}

val currentTab by remember(navigator) {
derivedStateOf {
navigator.currentDestination?.contentKey.orDefault()
}
}

val topAppBarScrollBehavior = if (LocalPlatform.current.hasScrollingBug()) {
null
} else {
Expand All @@ -259,9 +278,7 @@ internal fun SettingsPageLayout(
if (navigator.canNavigateBack()) {
BackNavigationIconButton(
onNavigateBack = {
coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
navigator.navigateBack()
}
onClickBackOnListPage()
},
)
} else {
Expand All @@ -273,7 +290,7 @@ internal fun SettingsPageLayout(
windowInsets = paneContentWindowInsets.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
)
},
listPaneContent = {
listPaneContent = paneScope@{
PermanentDrawerSheet(
Modifier
.paneContentPadding()
Expand All @@ -285,18 +302,17 @@ internal fun SettingsPageLayout(
.verticalScroll(listPaneScrollState),
drawerContainerColor = Color.Unspecified,
) {
val scope = remember(this, navigator) {
val highlightSelectedItemState = rememberUpdatedState(layoutParametersState.highlightSelectedItem)
val scope = remember(this, navigator, currentTab, highlightSelectedItemState) {
object : SettingsDrawerScope(), ColumnScope by this {
@Composable
override fun Item(item: SettingsTab) {
NavigationDrawerItem(
icon = { Icon(getIcon(item), contentDescription = null) },
label = { Text(getName(item)) },
selected = item == currentTab,
selected = item == currentTab() && highlightSelectedItemState.value,
onClick = {
coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
}
onSelectedTab(item)
},
)
}
Expand All @@ -314,9 +330,8 @@ internal fun SettingsPageLayout(
// empty because our detailPaneContent already has it
detailPane = {
AnimatedContent(
navigator.currentDestination?.contentKey,
Modifier
.fillMaxSize(),
currentTab(),
Modifier.fillMaxSize(),
transitionSpec = LocalAniMotionScheme.current.animatedContent.topLevel,
) { navigationTab ->
val tab = navigationTab.orDefault()
Expand All @@ -330,9 +345,7 @@ internal fun SettingsPageLayout(
if (listDetailLayoutParameters.isSinglePane) {
BackNavigationIconButton(
{
coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
navigator.navigateBack(BackNavigationBehavior.PopUntilScaffoldValueChange)
}
onClickBackOnDetailPage()
},
)
}
Expand Down

0 comments on commit 45c4d1f

Please sign in to comment.