这是indexloc提供的服务,不要输入任何密码
Skip to content

Update logic for panes, back, and backgrounds #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ package com.tunjid.treenav.compose

import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Stable
Expand All @@ -37,7 +34,6 @@ import com.tunjid.treenav.Node
import com.tunjid.treenav.compose.MultiPaneDisplayState.Companion.children
import com.tunjid.treenav.compose.MultiPaneDisplayState.Companion.destination
import com.tunjid.treenav.compose.MultiPaneDisplayState.Companion.id
import com.tunjid.treenav.compose.MultiPaneDisplayState.Companion.paneContentTransform
import com.tunjid.treenav.compose.navigation3.decorators.rememberViewModelStoreNavEntryDecorator
import com.tunjid.treenav.compose.navigation3.runtime.NavEntry
import com.tunjid.treenav.compose.navigation3.runtime.rememberSavedStateNavEntryDecorator
Expand Down Expand Up @@ -363,32 +359,7 @@ private class MultiPaneDisplayScene<Pane, Destination : Node>(
CompositionLocalProvider(
LocalPaneScope provides scope
) {
with(scope) {
val paneModifier = remember(
isActive,
inPredictiveBack,
panedNavigationState.identityHash(),
animatedContentScope.transition.targetState,
) {
val contentTransform = entry.paneContentTransform(this)
val shouldAnimate =
contentTransform.targetContentEnter != EnterTransition.None
|| contentTransform.initialContentExit != ExitTransition.None

if (shouldAnimate) Modifier.animateEnterExit(
enter = contentTransform.targetContentEnter,
exit = contentTransform.initialContentExit,
)
else Modifier
}

Box(
modifier = paneModifier,
content = {
entry.Content()
}
)
}
entry.Content()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ package com.tunjid.treenav.compose
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.tunjid.treenav.Node
import com.tunjid.treenav.compose.navigation3.runtime.NavEntry
import com.tunjid.treenav.compose.panedecorators.PaneMappingDecorator
import com.tunjid.treenav.compose.panedecorators.PaneDecorator
import com.tunjid.treenav.compose.panedecorators.PaneMappingDecorator
import com.tunjid.treenav.compose.panedecorators.PaneRenderDecorator

/**
Expand Down Expand Up @@ -67,7 +70,6 @@ class MultiPaneDisplayState<NavigationState : Node, Destination : Node, Pane> in
ID_KEY to destination.id,
DESTINATION_KEY to destination,
CHILDREN_KEY to destination.children,
PANE_CONTENT_TRANSFORM_KEY to paneEntry.contentTransform,
),
content = { innerDestination ->
destinationContent(localPaneScope(), paneEntry, innerDestination)
Expand All @@ -84,19 +86,13 @@ class MultiPaneDisplayState<NavigationState : Node, Destination : Node, Pane> in
private const val ID_KEY = "com.tunjid.treenav.compose.id"
private const val DESTINATION_KEY = "com.tunjid.treenav.compose.destination"
private const val CHILDREN_KEY = "com.tunjid.treenav.compose.children"
private const val PANE_CONTENT_TRANSFORM_KEY =
"com.tunjid.treenav.compose.pane.enter.transition"

internal val NavEntry<*>.id get() = metadata[ID_KEY] as String
internal val NavEntry<*>.children get() = metadata[CHILDREN_KEY]

@Suppress("UNCHECKED_CAST")
internal inline fun <T : Node> NavEntry<*>.destination() =
metadata[DESTINATION_KEY] as T

@Suppress("UNCHECKED_CAST")
internal inline val NavEntry<*>.paneContentTransform
get() = metadata[PANE_CONTENT_TRANSFORM_KEY] as PaneScope<*, *>.() -> ContentTransform
}
}

Expand Down Expand Up @@ -146,7 +142,28 @@ fun <NavigationState : Node, Destination : Node, Pane> MultiPaneDisplayState(
entryProvider(destination).paneMapping(destination)
},
destinationContent = transform@{ paneEntry, destination ->
paneEntry.content(this@transform, destination)
Box(
modifier = remember(
isActive,
inPredictiveBack,
paneState.pane,
transition.targetState,
) {
val contentTransform = paneEntry.contentTransform(this)
val shouldAnimate =
contentTransform.targetContentEnter != EnterTransition.None
|| contentTransform.initialContentExit != ExitTransition.None

if (shouldAnimate) Modifier.animateEnterExit(
enter = contentTransform.targetContentEnter,
exit = contentTransform.initialContentExit,
)
else Modifier
},
content = {
paneEntry.content(this@transform, destination)
}
)
}
),
operation = MultiPaneDisplayState<NavigationState, Destination, Pane>::plus
Expand Down

This file was deleted.

8 changes: 4 additions & 4 deletions libraryVersion.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# limitations under the License.
#
groupId=com.tunjid.treenav
treenav_version=0.0.41
strings_version=0.0.41
compose_version=0.0.41
compose-threepane_version=0.0.41
treenav_version=0.0.42
strings_version=0.0.42
compose_version=0.0.42
compose-threepane_version=0.0.42
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round
import androidx.navigationevent.NavigationEvent
import com.tunjid.composables.backpreview.BackPreviewState
import com.tunjid.composables.backpreview.backPreview
import com.tunjid.composables.splitlayout.SplitLayout
import com.tunjid.composables.splitlayout.SplitLayoutState
import com.tunjid.demo.common.ui.AppState.Companion.rememberMultiPaneDisplayState
Expand All @@ -84,11 +83,10 @@ import com.tunjid.treenav.compose.MultiPaneDisplayState
import com.tunjid.treenav.compose.moveablesharedelement.MovableSharedElementHostState
import com.tunjid.treenav.compose.multiPaneDisplayBackstack
import com.tunjid.treenav.compose.navigation3.ui.NavigationEventHandler
import com.tunjid.treenav.compose.panedecorators.PaneDecorator
import com.tunjid.treenav.compose.threepane.ThreePane
import com.tunjid.treenav.compose.threepane.panedecorators.threePaneAdaptiveDecorator
import com.tunjid.treenav.compose.threepane.panedecorators.threePaneMovableSharedElementDecorator
import com.tunjid.treenav.compose.panedecorators.PaneDecorator
import com.tunjid.treenav.compose.panedecorators.paneModifierDecorator
import com.tunjid.treenav.pop
import com.tunjid.treenav.popToRoot
import com.tunjid.treenav.requireCurrent
Expand Down Expand Up @@ -130,17 +128,6 @@ fun App(
threePaneMovableSharedElementDecorator(
movableSharedElementHostState = movableSharedElementHostState
),
paneModifierDecorator {
if (paneState.pane == ThreePane.Primary
&& inPredictiveBack
&& isActive
&& !appState.dragToPopState.isDraggingToPop
) Modifier
.fillMaxSize()
.backPreview(appState.backPreviewState)
else Modifier
.fillMaxSize()
},
)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.tunjid.demo.common.ui
import androidx.compose.animation.BoundsTransform
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.animateBounds
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.snap
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Box
Expand All @@ -31,6 +32,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
Expand Down Expand Up @@ -75,6 +77,19 @@ class PaneScaffoldState internal constructor(

internal var scaffoldTargetSize by mutableStateOf(IntSize.Zero)
internal var scaffoldCurrentSize by mutableStateOf(IntSize.Zero)

internal val defaultContainerColor: Color
@Composable get() {
val elevation by animateDpAsState(
if (paneState.pane == ThreePane.Primary
&& isActive
&& inPredictiveBack
) 4.dp
else 0.dp
)

return MaterialTheme.colorScheme.surfaceColorAtElevation(elevation)
}
}

@Composable
Expand All @@ -95,7 +110,7 @@ fun PaneScope<ThreePane, SampleDestination>.rememberPaneScaffoldState(): PaneSca
@Composable
fun PaneScaffoldState.PaneScaffold(
modifier: Modifier = Modifier,
containerColor: Color = MaterialTheme.colorScheme.background,
containerColor: Color = defaultContainerColor,
snackBarMessages: List<String> = emptyList(),
onSnackBarMessageConsumed: (String) -> Unit = {},
topBar: @Composable PaneScaffoldState.() -> Unit = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,46 @@

package com.tunjid.demo.common.ui

import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animate
import androidx.compose.animation.core.spring
import androidx.compose.foundation.background
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import com.tunjid.composables.backpreview.backPreview
import com.tunjid.demo.common.ui.data.SampleDestination
import com.tunjid.treenav.compose.PaneScope
import com.tunjid.treenav.compose.threepane.ThreePane
import com.tunjid.treenav.compose.threepane.adaptTo

@Composable
fun Modifier.predictiveBackBackgroundModifier(
paneScope: PaneScope<ThreePane, *>,
): Modifier {
if (paneScope.paneState.pane != ThreePane.Primary
|| !paneScope.isActive
|| !paneScope.inPredictiveBack
) return this
): Modifier = with(paneScope) {
val appState = LocalAppState.current
val shouldDrawBackground = paneState.pane == ThreePane.Primary
&& inPredictiveBack
&& isActive
&& !appState.dragToPopState.isDraggingToPop

var elevation by remember { mutableStateOf(0.dp) }
LaunchedEffect(Unit) {
animate(
initialValue = 0f,
targetValue = 4f,
animationSpec = spring(stiffness = Spring.StiffnessVeryLow)
) { value, _ -> elevation = value.dp }
}
return background(
color = MaterialTheme.colorScheme.surfaceColorAtElevation(elevation),
shape = RoundedCornerShape(16.dp)
val clipRadius by animateDpAsState(
if (shouldDrawBackground) 16.dp
else 0.dp
)
.clip(RoundedCornerShape(16.dp))

if (shouldDrawBackground) backPreview(appState.backPreviewState)
.clip(RoundedCornerShape(clipRadius))
else this@predictiveBackBackgroundModifier
}

val predictiveBackContentTransform: PaneScope<ThreePane, SampleDestination>.() -> ContentTransform =
{
ContentTransform(
fadeIn(),
fadeOut(targetAlpha = if (inPredictiveBack) 0.9f else 0f),
).adaptTo(paneScope = this)
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.tunjid.demo.common.ui.PaneScaffold
import com.tunjid.demo.common.ui.data.SampleDestination
import com.tunjid.demo.common.ui.data.SampleDestination.NavTabs
import com.tunjid.demo.common.ui.predictiveBackBackgroundModifier
import com.tunjid.demo.common.ui.rememberPaneScaffoldState
import com.tunjid.demo.common.ui.viewModelCoroutineScope
import com.tunjid.treenav.compose.threepane.ThreePane
Expand All @@ -49,7 +50,8 @@ fun avatarPaneEntry() = threePaneEntry<SampleDestination>(
}
rememberPaneScaffoldState().PaneScaffold(
modifier = Modifier
.fillMaxSize(),
.fillMaxSize()
.predictiveBackBackgroundModifier(this),
containerColor = Color.Transparent,
content = {
AvatarScreen(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ import com.tunjid.demo.common.ui.PaneScaffold
import com.tunjid.demo.common.ui.data.SampleDestination
import com.tunjid.demo.common.ui.data.SampleDestination.NavTabs
import com.tunjid.demo.common.ui.predictiveBackBackgroundModifier
import com.tunjid.demo.common.ui.predictiveBackContentTransform
import com.tunjid.demo.common.ui.rememberPaneScaffoldState
import com.tunjid.demo.common.ui.viewModelCoroutineScope
import com.tunjid.treenav.compose.threepane.ThreePane
import com.tunjid.treenav.compose.threepane.threePaneEntry

fun chatPaneEntry() = threePaneEntry<SampleDestination>(
fun chatPaneEntry() = threePaneEntry(
contentTransform = predictiveBackContentTransform,
paneMapping = { destination ->
mapOf(
ThreePane.Primary to destination,
Expand All @@ -48,8 +50,8 @@ fun chatPaneEntry() = threePaneEntry<SampleDestination>(
}
rememberPaneScaffoldState().PaneScaffold(
modifier = Modifier
.predictiveBackBackgroundModifier(this)
.fillMaxSize(),
.fillMaxSize()
.predictiveBackBackgroundModifier(this),
content = {
ChatScreen(
paneScaffoldState = this,
Expand Down
Loading