From 269615eba0634bc6f546dd2882f5c7b0ca1d56d8 Mon Sep 17 00:00:00 2001 From: Adetunji Dahunsi Date: Fri, 11 Oct 2024 07:45:18 -0400 Subject: [PATCH 1/5] Remove Adaptive prefix on some classes and methods --- .../treenav/adaptive/AdaptivePaneStrategy.kt | 43 -------- .../{AdaptivePaneScope.kt => PaneScope.kt} | 24 ++-- .../tunjid/treenav/adaptive/PaneStrategy.kt | 45 ++++++++ .../{AdaptiveNavHost.kt => PanedNavHost.kt} | 12 +- ...ration.kt => PanedNavHostConfiguration.kt} | 32 +++--- ...gationState.kt => PanedNavigationState.kt} | 5 +- ...tate.kt => SavedStatePanedNavHostState.kt} | 44 ++++---- ...te.kt => SlotBasedPanedNavigationState.kt} | 20 ++-- .../lifecycle/DestinationLifecycleOwner.kt | 10 +- .../MovableSharedElementState.kt | 12 +- .../MovableSharedElements.kt | 22 ++-- .../treenav/adaptive/threepane/ThreePane.kt | 104 ++++++++++++------ .../MovableSharedElementConfiguration.kt | 35 +++--- .../ThreePaneAdaptiveConfiguration.kt | 12 +- .../SlotBasedAdaptiveNavigationStateTest.kt | 6 +- .../com/tunjid/demo/common/ui/DemoApp.kt | 32 +++--- .../demo/common/ui/chat/Configuration.kt | 4 +- .../demo/common/ui/chatrooms/Configuration.kt | 4 +- .../demo/common/ui/profile/Configuration.kt | 4 +- .../demo/common/ui/settings/Configuration.kt | 4 +- 20 files changed, 262 insertions(+), 212 deletions(-) delete mode 100644 library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptivePaneStrategy.kt rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/{AdaptivePaneScope.kt => PaneScope.kt} (73%) create mode 100644 library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneStrategy.kt rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/{AdaptiveNavHost.kt => PanedNavHost.kt} (72%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/{AdaptiveNavHostConfiguration.kt => PanedNavHostConfiguration.kt} (72%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/{AdaptiveNavigationState.kt => PanedNavigationState.kt} (91%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/{SavedStateAdaptiveNavHostState.kt => SavedStatePanedNavHostState.kt} (87%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/{SlotBasedAdaptiveNavigationState.kt => SlotBasedPanedNavigationState.kt} (90%) diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptivePaneStrategy.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptivePaneStrategy.kt deleted file mode 100644 index c53f882..0000000 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptivePaneStrategy.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.tunjid.treenav.adaptive - -import androidx.compose.animation.EnterTransition -import androidx.compose.animation.ExitTransition -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Stable -import com.tunjid.treenav.Node - -/** - * Provides adaptive strategy in panes [Pane] for a given navigation destination [Destination]. - */ -@Stable -class AdaptivePaneStrategy internal constructor( - val transitions: AdaptivePaneScope.() -> AdaptivePaneScope.Transitions, - /** - * Defines what route to show in the secondary panel alongside this route - */ - val paneMapper: @Composable (Destination) -> Map, - val render: @Composable AdaptivePaneScope.(Destination) -> Unit -) - -/** - * Allows for defining the adaptation strategy in panes [Pane] for a given navigation destination [Destination]. - * - * @param transitions the transitions to run within each [AdaptivePaneScope]. - * @param paneMapping provides the mapping of panes to destinations for a given destination [Destination]. - * @param render defines the Composable rendered for each destination - * in a given [AdaptivePaneScope]. - */ -fun adaptivePaneStrategy( - transitions: AdaptivePaneScope.() -> AdaptivePaneScope.Transitions = { NoTransition }, - paneMapping: @Composable (Destination) -> Map = { emptyMap() }, - render: @Composable AdaptivePaneScope.(Destination) -> Unit -) = AdaptivePaneStrategy( - paneMapper = paneMapping, - transitions = transitions, - render = render -) - -private val NoTransition = AdaptivePaneScope.Transitions( - enter = EnterTransition.None, - exit = ExitTransition.None, -) \ No newline at end of file diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptivePaneScope.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneScope.kt similarity index 73% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptivePaneScope.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneScope.kt index b4ef94e..afe7f52 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptivePaneScope.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneScope.kt @@ -32,15 +32,15 @@ import kotlin.jvm.JvmInline * Scope for adaptive content that can show up in an arbitrary pane. */ @Stable -interface AdaptivePaneScope : AnimatedVisibilityScope { +interface PaneScope : AnimatedVisibilityScope { /** - * Provides information about the adaptive context that created this [AdaptivePaneScope]. + * Provides information about the adaptive context that created this [PaneScope]. */ - val paneState: AdaptivePaneState + val paneState: PaneState /** - * Whether or not this [AdaptivePaneScope] is active in its current pane. It is inactive when + * Whether or not this [PaneScope] is active in its current pane. It is inactive when * it is animating out of its [AnimatedVisibilityScope]. */ val isActive: Boolean @@ -55,14 +55,14 @@ interface AdaptivePaneScope : AnimatedVisibilityScope } /** - * An implementation of [AdaptivePaneScope] that supports animations and shared elements + * An implementation of [PaneScope] that supports animations and shared elements */ @Stable -internal class AnimatedAdaptivePaneScope( - paneState: AdaptivePaneState, +internal class AnimatedPaneScope( + paneState: PaneState, activeState: State, val animatedContentScope: AnimatedContentScope -) : AdaptivePaneScope, AnimatedVisibilityScope by animatedContentScope { +) : PaneScope, AnimatedVisibilityScope by animatedContentScope { override var paneState by mutableStateOf(paneState) @@ -73,14 +73,14 @@ internal class AnimatedAdaptivePaneScope( * Information about content in a pane */ @Stable -sealed interface AdaptivePaneState { +sealed interface PaneState { val currentDestination: Destination? val pane: Pane? val adaptations: Set } /** - * [Slot] based implementation of [AdaptivePaneState] + * [Slot] based implementation of [PaneState] */ internal data class SlotPaneState( val slot: Slot?, @@ -88,10 +88,10 @@ internal data class SlotPaneState( override val currentDestination: Destination?, override val pane: Pane?, override val adaptations: Set, -) : AdaptivePaneState +) : PaneState /** - * A spot taken by an [AdaptivePaneStrategy] that may be moved in from pane to pane. + * A spot taken by an [PaneStrategy] that may be moved in from pane to pane. */ @JvmInline internal value class Slot internal constructor(val index: Int) diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneStrategy.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneStrategy.kt new file mode 100644 index 0000000..4dbcefa --- /dev/null +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneStrategy.kt @@ -0,0 +1,45 @@ +package com.tunjid.treenav.adaptive + +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import com.tunjid.treenav.Node + +/** + * Provides the logic used to select, configure and place a navigation [Destination] for each + * pane [Pane] for the current active navigation [Destination]. + */ +@Stable +class PaneStrategy internal constructor( + val transitions: PaneScope.() -> PaneScope.Transitions, + /** + * Defines what route to show in the secondary panel alongside this route + */ + val paneMapper: @Composable (Destination) -> Map, + val render: @Composable PaneScope.(Destination) -> Unit +) + +/** + * Allows for defining the logic used to select, configure and place a navigation + * [Destination] for each pane [Pane] for the current active navigation [Destination]. + * + * @param transitions the transitions to run within each [PaneScope]. + * @param paneMapping provides the mapping of panes to destinations for a given destination [Destination]. + * @param render defines the Composable rendered for each destination + * in a given [PaneScope]. + */ +fun paneStrategy( + transitions: PaneScope.() -> PaneScope.Transitions = { NoTransition }, + paneMapping: @Composable (Destination) -> Map = { emptyMap() }, + render: @Composable PaneScope.(Destination) -> Unit +) = PaneStrategy( + paneMapper = paneMapping, + transitions = transitions, + render = render +) + +private val NoTransition = PaneScope.Transitions( + enter = EnterTransition.None, + exit = ExitTransition.None, +) \ No newline at end of file diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptiveNavHost.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHost.kt similarity index 72% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptiveNavHost.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHost.kt index bd43da9..2b9fa73 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptiveNavHost.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHost.kt @@ -24,18 +24,18 @@ import com.tunjid.treenav.Node /** * Creates a host for adaptive navigation for panes [Pane] and destinations [Destination]. * - * @param state the [AdaptiveNavHostState] producing the [AdaptiveNavHostScope] that provides - * context about the panes in [AdaptiveNavHost]. + * @param state the [PanedNavHostState] producing the [PanedNavHostScope] that provides + * context about the panes in [PanedNavHost]. * @param modifier The modifier to be applied to the layout. - * @param content [AdaptiveNavHostScope] receiving lambda allowing for placing each pane in its + * @param content [PanedNavHostScope] receiving lambda allowing for placing each pane in its * appropriate slot. * */ @Composable -fun AdaptiveNavHost( - state: AdaptiveNavHostState, +fun PanedNavHost( + state: PanedNavHostState, modifier: Modifier = Modifier, - content: @Composable AdaptiveNavHostScope.() -> Unit + content: @Composable PanedNavHostScope.() -> Unit ) { Box( modifier = modifier diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptiveNavHostConfiguration.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHostConfiguration.kt similarity index 72% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptiveNavHostConfiguration.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHostConfiguration.kt index 30956dd..d656df9 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptiveNavHostConfiguration.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHostConfiguration.kt @@ -27,7 +27,7 @@ import androidx.compose.ui.Modifier import com.tunjid.treenav.Node /** - * Class for configuring an [AdaptiveNavHost] for adapting different navigation + * Class for configuring a [PanedNavHost] for selecting, adapting and placing navigation * destinations into different panes from an arbitrary [navigationState]. * * @param navigationState the navigation state to be adapted into various panes. @@ -36,10 +36,10 @@ import com.tunjid.treenav.Node * panes available. */ @Stable -class AdaptiveNavHostConfiguration internal constructor( +class PanedNavHostConfiguration internal constructor( val navigationState: State, val destinationTransform: (NavigationState) -> Destination, - val strategyTransform: (destination: Destination) -> AdaptivePaneStrategy + val strategyTransform: (destination: Destination) -> PaneStrategy ) { internal val currentDestination: State = derivedStateOf { destinationTransform(navigationState.value) @@ -47,7 +47,7 @@ class AdaptiveNavHostConfiguration adaptiveNavHostConfiguration( +fun panedNavHostConfiguration( navigationState: State, destinationTransform: (NavigationState) -> Destination, - strategyTransform: (destination: Destination) -> AdaptivePaneStrategy -) = AdaptiveNavHostConfiguration( + strategyTransform: (destination: Destination) -> PaneStrategy +) = PanedNavHostConfiguration( navigationState = navigationState, destinationTransform = destinationTransform, strategyTransform = strategyTransform, ) /** - * Creates a new [AdaptiveNavHost] by delegating to [this] and rendering destinations into different panes. + * Creates a new [PanedNavHost] by delegating to [this] and rendering destinations into different panes. * - * @param destinationTransform a transform of [AdaptiveNavHostConfiguration.navigationState] + * @param destinationTransform a transform of [PanedNavHostConfiguration.navigationState] * to its current destination. It is read inside a [derivedStateOf] block, so reads of snapshot * state objects will be observed. * @param strategyTransform provides the strategy used to adapt the current destination to the * panes available. */ -fun AdaptiveNavHostConfiguration.delegated( +fun PanedNavHostConfiguration.delegated( destinationTransform: (NavigationState) -> Destination = this@delegated.destinationTransform, - strategyTransform: (destination: Destination) -> AdaptivePaneStrategy -) = adaptiveNavHostConfiguration( + strategyTransform: (destination: Destination) -> PaneStrategy +) = panedNavHostConfiguration( navigationState = this@delegated.navigationState, destinationTransform = destinationTransform, strategyTransform = strategyTransform, @@ -90,8 +90,8 @@ fun AdaptiveNavHostConfigurat * The current destination in a given [paneScope]. */ @Composable -internal fun AdaptiveNavHostConfiguration.Destination( - paneScope: AdaptivePaneScope +internal fun PanedNavHostConfiguration.Destination( + paneScope: PaneScope ) { val current = remember(paneScope.paneState.currentDestination) { paneScope.paneState.currentDestination @@ -112,10 +112,10 @@ internal fun AdaptiveNavHostConfiguration AdaptiveNavHostConfiguration.paneMapping(): Map { +internal fun PanedNavHostConfiguration.paneMapping(): Map { val current by currentDestination return current.let { strategyTransform(it).paneMapper(it) diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptiveNavigationState.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavigationState.kt similarity index 91% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptiveNavigationState.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavigationState.kt index 5c1e978..6beabe1 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/AdaptiveNavigationState.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavigationState.kt @@ -5,7 +5,7 @@ import com.tunjid.treenav.Node /** * State providing details about data in each pane [Pane] it hosts. */ -interface AdaptiveNavigationState { +interface PanedNavigationState { /** * The current [Destination] in this [pane]. @@ -25,7 +25,8 @@ interface AdaptiveNavigationState { } /** - * A description of the process that the layout undertook to adapt to its new configuration. + * A description of the process that the layout undertook to adapt to the present + * pane in its new configuration. */ sealed class Adaptation { diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SavedStateAdaptiveNavHostState.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SavedStatePanedNavHostState.kt similarity index 87% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SavedStateAdaptiveNavHostState.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SavedStatePanedNavHostState.kt index 51ca896..4136ab5 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SavedStateAdaptiveNavHostState.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SavedStatePanedNavHostState.kt @@ -34,20 +34,20 @@ import com.tunjid.treenav.traverse * A host for adaptive navigation for panes [Pane] and destinations [Destination]. */ @Stable -interface AdaptiveNavHostState { +interface PanedNavHostState { /** - * Creates the scope that provides context about individual panes [Pane] in an [AdaptiveNavHost]. + * Creates the scope that provides context about individual panes [Pane] in an [PanedNavHost]. */ @Composable - fun scope(): AdaptiveNavHostScope + fun scope(): PanedNavHostScope } /** - * Scope that provides context about individual panes [Pane] in an [AdaptiveNavHost]. + * Scope that provides context about individual panes [Pane] in an [PanedNavHost]. */ @Stable -interface AdaptiveNavHostScope { +interface PanedNavHostScope { @Composable fun Destination( @@ -64,29 +64,29 @@ interface AdaptiveNavHostScope { } /** - * An implementation of an [AdaptiveNavHostState] that provides a [SaveableStateHolder] for each + * An implementation of an [PanedNavHostState] that provides a [SaveableStateHolder] for each * navigation destination that shows up in its panes. * - * @param panes a list of panes that is possible to show in the [AdaptiveNavHost] in all + * @param panes a list of panes that is possible to show in the [PanedNavHost] in all * possible configurations. The panes should consist of enum class instances, or a sealed class * hierarchy of kotlin objects. - * @param configuration the [AdaptiveNavHostConfiguration] that applies adaptive semantics and - * strategies for each navigation destination shown in the [AdaptiveNavHost]. + * @param configuration the [PanedNavHostConfiguration] that applies adaptive semantics and + * strategies for each navigation destination shown in the [PanedNavHost]. */ @Stable -class SavedStateAdaptiveNavHostState( +class SavedStatePanedNavHostState( private val panes: List, - private val configuration: AdaptiveNavHostConfiguration, -) : AdaptiveNavHostState { + private val configuration: PanedNavHostConfiguration, +) : PanedNavHostState { @Composable - override fun scope(): AdaptiveNavHostScope { + override fun scope(): PanedNavHostScope { val navigationState by configuration.navigationState val panesToNodes = configuration.paneMapping() val saveableStateHolder = rememberSaveableStateHolder() val adaptiveContentScope = remember { - SavedStateAdaptiveNavHostScope( + SavedStatePanedNavHostScope( panes = panes, navHostConfiguration = configuration, initialPanesToNodes = panesToNodes, @@ -106,12 +106,12 @@ class SavedStateAdaptiveNavHostState( companion object { @Stable - private class SavedStateAdaptiveNavHostScope( + private class SavedStatePanedNavHostScope( panes: List, initialPanesToNodes: Map, saveableStateHolder: SaveableStateHolder, - val navHostConfiguration: AdaptiveNavHostConfiguration, - ) : AdaptiveNavHostScope, SaveableStateHolder by saveableStateHolder { + val navHostConfiguration: PanedNavHostConfiguration, + ) : PanedNavHostScope, SaveableStateHolder by saveableStateHolder { private val destinationViewModelStoreCreator = DestinationViewModelStoreCreator( rootNodeProvider = navHostConfiguration.navigationState::value @@ -123,7 +123,7 @@ class SavedStateAdaptiveNavHostState( ).toSet() var adaptiveNavigationState by mutableStateOf( - value = SlotBasedAdaptiveNavigationState.initial(slots = slots) + value = SlotBasedPanedNavigationState.initial(slots = slots) .adaptTo( slots = slots, panesToNodes = initialPanesToNodes, @@ -189,7 +189,7 @@ class SavedStateAdaptiveNavHostState( } ) { targetPaneState -> val scope = remember { - AnimatedAdaptivePaneScope( + AnimatedPaneScope( paneState = targetPaneState, activeState = derivedStateOf { val activePaneState = adaptiveNavigationState.paneStateFor(slot) @@ -235,13 +235,13 @@ class SavedStateAdaptiveNavHostState( ) { destinationLifecycleOwner.update( hostLifecycleState = hostLifecycleState, - adaptivePaneScope = scope, + paneScope = scope, adaptiveNavigationState = adaptiveNavigationState ) onDispose { destinationLifecycleOwner.update( hostLifecycleState = hostLifecycleState, - adaptivePaneScope = scope, + paneScope = scope, adaptiveNavigationState = adaptiveNavigationState ) } @@ -274,7 +274,7 @@ class SavedStateAdaptiveNavHostState( } private inline fun updateAdaptiveNavigationState( - block: SlotBasedAdaptiveNavigationState.() -> SlotBasedAdaptiveNavigationState + block: SlotBasedPanedNavigationState.() -> SlotBasedPanedNavigationState ) { adaptiveNavigationState = adaptiveNavigationState.block() } diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SlotBasedAdaptiveNavigationState.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SlotBasedPanedNavigationState.kt similarity index 90% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SlotBasedAdaptiveNavigationState.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SlotBasedPanedNavigationState.kt index 2a8a891..f1efd84 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SlotBasedAdaptiveNavigationState.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SlotBasedPanedNavigationState.kt @@ -24,7 +24,7 @@ import com.tunjid.treenav.adaptive.Adaptation.Change.contains * Data structure for managing navigation as it adapts to various layout configurations */ @Immutable -internal data class SlotBasedAdaptiveNavigationState( +internal data class SlotBasedPanedNavigationState( /** * Moves between panes within a navigation sequence. */ @@ -49,11 +49,11 @@ internal data class SlotBasedAdaptiveNavigationState( * A set of node ids that are animating out. */ val destinationIdsAnimatingOut: Set, -) : AdaptiveNavigationState { +) : PanedNavigationState { companion object { internal fun initial( slots: Collection, - ): SlotBasedAdaptiveNavigationState = SlotBasedAdaptiveNavigationState( + ): SlotBasedPanedNavigationState = SlotBasedPanedNavigationState( swapAdaptations = emptySet(), panesToDestinations = emptyMap(), destinationIdsToAdaptiveSlots = slots.associateBy( @@ -67,7 +67,7 @@ internal data class SlotBasedAdaptiveNavigationState( internal fun paneStateFor( slot: Slot - ): AdaptivePaneState { + ): PaneState { val node = destinationFor(slot) val pane = node?.let(::paneFor) return SlotPaneState( @@ -121,11 +121,11 @@ internal data class SlotBasedAdaptiveNavigationState( * A method that adapts changes in navigation to different panes while allowing for them * to be animated easily. */ -internal fun SlotBasedAdaptiveNavigationState.adaptTo( +internal fun SlotBasedPanedNavigationState.adaptTo( slots: Set, panesToNodes: Map, backStackIds: Set, -): SlotBasedAdaptiveNavigationState { +): SlotBasedPanedNavigationState { val previous = this val previouslyUsedSlots = previous.destinationIdsToAdaptiveSlots @@ -178,7 +178,7 @@ internal fun SlotBasedAdaptiveNavigationState.adaptTo( nodeIdsToAdaptiveSlots[nodeId] = availableSlots.first().also(availableSlots::remove) } - return SlotBasedAdaptiveNavigationState( + return SlotBasedPanedNavigationState( // If the values of the nodes to panes are the same, no swaps occurred. swapAdaptations = when (previous.panesToDestinations.mapValues { it.value?.id }) { panesToNodes.mapValues { it.value?.id } -> previous.swapAdaptations @@ -198,7 +198,7 @@ internal fun SlotBasedAdaptiveNavigationState.adaptTo( /** * Checks if any of the new routes coming in has any conflicts with those animating out. */ -internal fun SlotBasedAdaptiveNavigationState.hasConflictingRoutes(): Boolean = +internal fun SlotBasedPanedNavigationState.hasConflictingRoutes(): Boolean = panesToDestinations.keys .map(::destinationFor) .any { @@ -206,9 +206,9 @@ internal fun SlotBasedAdaptiveNavigationState SlotBasedAdaptiveNavigationState.prune(): SlotBasedAdaptiveNavigationState = +internal fun SlotBasedPanedNavigationState.prune(): SlotBasedPanedNavigationState = copy( destinationIdsToAdaptiveSlots = destinationIdsToAdaptiveSlots.filter { (routeId) -> if (routeId == null) return@filter false diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/lifecycle/DestinationLifecycleOwner.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/lifecycle/DestinationLifecycleOwner.kt index a506e0d..010de17 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/lifecycle/DestinationLifecycleOwner.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/lifecycle/DestinationLifecycleOwner.kt @@ -9,8 +9,8 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import androidx.lifecycle.compose.LocalLifecycleOwner import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.AdaptivePaneScope -import com.tunjid.treenav.adaptive.SlotBasedAdaptiveNavigationState +import com.tunjid.treenav.adaptive.PaneScope +import com.tunjid.treenav.adaptive.SlotBasedPanedNavigationState @Composable internal fun rememberDestinationLifecycleOwner( @@ -41,10 +41,10 @@ internal class DestinationLifecycleOwner( fun update( hostLifecycleState: State, - adaptivePaneScope: AdaptivePaneScope<*, *>, - adaptiveNavigationState: SlotBasedAdaptiveNavigationState<*, *>, + paneScope: PaneScope<*, *>, + adaptiveNavigationState: SlotBasedPanedNavigationState<*, *>, ) { - val active = adaptivePaneScope.isActive + val active = paneScope.isActive val exists = adaptiveNavigationState.backStackIds.contains( destination.id ) diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElementState.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElementState.kt index 65a8aa3..9177310 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElementState.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElementState.kt @@ -34,20 +34,20 @@ import androidx.compose.ui.unit.toOffset import androidx.compose.ui.unit.toSize import androidx.compose.ui.util.fastRoundToInt import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.AdaptivePaneScope -import com.tunjid.treenav.adaptive.AdaptivePaneState +import com.tunjid.treenav.adaptive.PaneScope +import com.tunjid.treenav.adaptive.PaneState import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.first @Stable @OptIn(ExperimentalSharedTransitionApi::class) internal class MovableSharedElementState( - paneScope: AdaptivePaneScope, + paneScope: PaneScope, sharedTransitionScope: SharedTransitionScope, sharedElement: @Composable (State, Modifier) -> Unit, onRemoved: () -> Unit, private val boundsTransform: BoundsTransform, - private val canAnimateOnStartingFrames: AdaptivePaneState.() -> Boolean + private val canAnimateOnStartingFrames: PaneState.() -> Boolean ) : SharedElementOverlay, SharedTransitionScope by sharedTransitionScope { var paneScope by mutableStateOf(paneScope) @@ -97,7 +97,7 @@ internal class MovableSharedElementState( } private fun updatePaneStateSeen( - paneState: AdaptivePaneState<*, *> + paneState: PaneState<*, *> ) { panesKeysToSeenCount[paneState.key] = Unit } @@ -231,4 +231,4 @@ internal class MovableSharedElementState( } } -private val AdaptivePaneState<*, *>.key get() = "${currentDestination?.id}-$pane" +private val PaneState<*, *>.key get() = "${currentDestination?.id}-$pane" diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElements.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElements.kt index 7d2b5ff..f8eae96 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElements.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElements.kt @@ -17,16 +17,16 @@ import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.drawscope.ContentDrawScope import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.AdaptiveNavHost -import com.tunjid.treenav.adaptive.AdaptivePaneScope -import com.tunjid.treenav.adaptive.AdaptivePaneState +import com.tunjid.treenav.adaptive.PanedNavHost +import com.tunjid.treenav.adaptive.PaneScope +import com.tunjid.treenav.adaptive.PaneState internal interface SharedElementOverlay { fun ContentDrawScope.drawInOverlay() } /** - * Creates movable shared elements that may be shared amongst different [AdaptivePaneScope] + * Creates movable shared elements that may be shared amongst different [PaneScope] * instances. */ interface MovableSharedElementScope { @@ -50,13 +50,13 @@ interface MovableSharedElementScope { } /** - * State for managing movable shared elements within a single [AdaptiveNavHost]. + * State for managing movable shared elements within a single [PanedNavHost]. */ @OptIn(ExperimentalSharedTransitionApi::class) @Stable class MovableSharedElementHostState( private val sharedTransitionScope: SharedTransitionScope, - private val canAnimateOnStartingFrames: (AdaptivePaneState) -> Boolean, + private val canAnimateOnStartingFrames: (PaneState) -> Boolean, ) { // TODO: This should be unnecessary. Figure out a way to participate arbitrarily in the @@ -86,11 +86,11 @@ class MovableSharedElementHostState( keysToMovableSharedElements.contains(key) /** - * Provides a movable shared element that can be rendered in a given [AdaptivePaneScope]. + * Provides a movable shared element that can be rendered in a given [PaneScope]. * It is the callers responsibility to perform other verifications on the ability - * of the calling [AdaptivePaneScope] to render the movable shared element. + * of the calling [PaneScope] to render the movable shared element. */ - fun AdaptivePaneScope.createOrUpdateSharedElement( + fun PaneScope.createOrUpdateSharedElement( key: Any, boundsTransform: BoundsTransform, sharedElement: @Composable (S, Modifier) -> Unit, @@ -113,14 +113,14 @@ class MovableSharedElementHostState( /** * An implementation of [MovableSharedElementScope] that ensures shared elements are only rendered - * in an [AdaptivePaneScope] when it is active. + * in an [PaneScope] when it is active. * * Other implementations of [MovableSharedElementScope] may delegate to this for their own * movable shared element implementations. */ @Stable internal class AdaptiveMovableSharedElementScope( - paneScope: AdaptivePaneScope, + paneScope: PaneScope, private val movableSharedElementHostState: MovableSharedElementHostState, ) : MovableSharedElementScope { diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt index 0d71440..9f0e6a4 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt @@ -25,18 +25,44 @@ import androidx.compose.animation.fadeOut import androidx.compose.runtime.Composable import com.tunjid.treenav.Node import com.tunjid.treenav.adaptive.Adaptation.Swap -import com.tunjid.treenav.adaptive.AdaptivePaneScope -import com.tunjid.treenav.adaptive.AdaptivePaneStrategy -import com.tunjid.treenav.adaptive.adaptivePaneStrategy +import com.tunjid.treenav.adaptive.PaneScope +import com.tunjid.treenav.adaptive.PaneStrategy +import com.tunjid.treenav.adaptive.paneStrategy /** - * A layout in the hierarchy that hosts an [AdaptivePaneStrategy] + * A [PaneStrategy] for apps that display up to 3 major panes as once. + * It also provides extra panes for transient content. */ enum class ThreePane { + /** + * The pane for the foremost content the user is interacting with. This is typically the + * actual navigation destination. + */ Primary, + + /** + * A optional pane for placing content from the [Primary] pane, if a preview of the previous + * navigation destinations is occurring. The primary content is rendered here, while + * the previous primary content is rendered in the [Primary] pane. + */ TransientPrimary, + + /** + * An optional pane for displaying a navigation destination alongside the [Primary] pane. + * This is useful for list-detail, or supporting panels flows. + */ Secondary, + + /** + * An optional pane to display an navigation destination alongside both the [Primary] and + * [Secondary] panes. This is typically used when the screen is large enough to display 3 + * panes simultaneously. + */ Tertiary, + + /** + * An optional pane for showing dialogs, or context sheets over existing panes. + */ Overlay; companion object { @@ -57,37 +83,54 @@ enum class ThreePane { } } -fun threePaneAdaptiveNodeConfiguration( - transitions: AdaptivePaneScope.() -> AdaptivePaneScope.Transitions = { +/** + * A strategy for selectively running animations in list detail flows. When: + * * A navigation destination moves between the [ThreePane.Primary] and [ThreePane.Secondary] + * panes, the pane animations are not run to provide a seamless movement experience. + * * A navigation destination moves between the [ThreePane.Primary] and + * [ThreePane.TransientPrimary] panes, the pane animations are not run. + * + * @param enterTransition the transition to run for the entering pane when permitted. + * @param exitTransition the transition to run for the exiting pane when permitted. + * @param paneMapping the mapping of panes to navigation destinations. + * @param render the Composable for rendering the current destination. + */ +fun threePaneListDetailAnimationStrategy( + enterTransition: PaneScope.() -> EnterTransition = { DefaultFadeIn }, + exitTransition: PaneScope.() -> ExitTransition = { DefaultFadeOut }, + paneMapping: @Composable (R) -> Map = { + mapOf(ThreePane.Primary to it) + }, + render: @Composable PaneScope.(R) -> Unit +): PaneStrategy = paneStrategy( + paneMapping = paneMapping, + transitions = { val state = paneState when (state.pane) { ThreePane.Primary, - ThreePane.Secondary -> when (state.adaptations) { - ThreePane.PrimaryToSecondary, - ThreePane.SecondaryToPrimary -> NoTransition + ThreePane.Secondary -> when { + ThreePane.PrimaryToSecondary in state.adaptations + || ThreePane.SecondaryToPrimary in state.adaptations + -> NoTransition - else -> DefaultTransition + else -> PaneScope.Transitions( + enter = enterTransition(), + exit = exitTransition() + ) } - ThreePane.TransientPrimary -> when (state.adaptations) { - ThreePane.PrimaryToTransient -> when (state.pane) { - ThreePane.Secondary -> DefaultTransition - else -> NoTransition - } + ThreePane.TransientPrimary -> when { + ThreePane.PrimaryToTransient in state.adaptations -> NoTransition - else -> DefaultTransition + else -> PaneScope.Transitions( + enter = enterTransition(), + exit = exitTransition() + ) } else -> NoTransition } }, - paneMapping: @Composable (R) -> Map = { - mapOf(ThreePane.Primary to it) - }, - render: @Composable AdaptivePaneScope.(R) -> Unit -) = adaptivePaneStrategy( - paneMapping = paneMapping, - transitions = transitions, render = render ) @@ -95,16 +138,15 @@ private val RouteTransitionAnimationSpec: FiniteAnimationSpec = tween( durationMillis = 700 ) -private val DefaultTransition = AdaptivePaneScope.Transitions( - enter = fadeIn( - animationSpec = RouteTransitionAnimationSpec, - ), - exit = fadeOut( - animationSpec = RouteTransitionAnimationSpec - ) +private val DefaultFadeIn = fadeIn( + animationSpec = RouteTransitionAnimationSpec, +) + +private val DefaultFadeOut = fadeOut( + animationSpec = RouteTransitionAnimationSpec, ) -private val NoTransition = AdaptivePaneScope.Transitions( +private val NoTransition = PaneScope.Transitions( enter = EnterTransition.None, exit = ExitTransition.None, ) \ No newline at end of file diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/MovableSharedElementConfiguration.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/MovableSharedElementConfiguration.kt index 9dcc9fe..9117af2 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/MovableSharedElementConfiguration.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/MovableSharedElementConfiguration.kt @@ -11,28 +11,33 @@ import com.tunjid.scaffold.treenav.adaptive.moveablesharedelement.AdaptiveMovabl import com.tunjid.scaffold.treenav.adaptive.moveablesharedelement.MovableSharedElementHostState import com.tunjid.scaffold.treenav.adaptive.moveablesharedelement.MovableSharedElementScope import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.AdaptiveNavHost -import com.tunjid.treenav.adaptive.AdaptiveNavHostConfiguration -import com.tunjid.treenav.adaptive.AdaptivePaneScope -import com.tunjid.treenav.adaptive.AdaptivePaneState -import com.tunjid.treenav.adaptive.AdaptivePaneStrategy +import com.tunjid.treenav.adaptive.PanedNavHost +import com.tunjid.treenav.adaptive.PanedNavHostConfiguration +import com.tunjid.treenav.adaptive.PaneScope +import com.tunjid.treenav.adaptive.PaneState +import com.tunjid.treenav.adaptive.PaneStrategy import com.tunjid.treenav.adaptive.delegated import com.tunjid.treenav.adaptive.threepane.ThreePane /** - * An [AdaptiveNavHostConfiguration] that applies semantics of movable shared elements to + * An [PanedNavHostConfiguration] that applies semantics of movable shared elements to * [ThreePane] layouts. * * @param movableSharedElementHostState the host state for coordinating movable shared elements. - * There should be one instance of this per [AdaptiveNavHost]. + * There should be one instance of this per [PanedNavHost]. */ -fun AdaptiveNavHostConfiguration.movableSharedElementConfiguration( +fun PanedNavHostConfiguration< + ThreePane, + NavigationState, + Destination + >.threePaneMovableSharedElementConfiguration( movableSharedElementHostState: MovableSharedElementHostState, -): AdaptiveNavHostConfiguration = +): PanedNavHostConfiguration = delegated { destination -> - val originalStrategy = this@movableSharedElementConfiguration.strategyTransform(destination) - AdaptivePaneStrategy( + val originalStrategy = + this@threePaneMovableSharedElementConfiguration.strategyTransform(destination) + PaneStrategy( transitions = originalStrategy.transitions, paneMapper = originalStrategy.paneMapper, render = { paneDestination -> @@ -56,7 +61,7 @@ fun AdaptiveNavHostConfiguration AdaptivePaneScope.movableSharedElementScope(): MovableSharedElementScope { +fun PaneScope.movableSharedElementScope(): MovableSharedElementScope { check(this is ThreePaneMovableSharedElementScope) { """ The current AdaptivePaneScope (${this::class.qualifiedName}) is not an instance of @@ -73,7 +78,7 @@ private class ThreePaneMovableSharedElementScope( private val hostState: MovableSharedElementHostState, private val delegate: AdaptiveMovableSharedElementScope, ) : MovableSharedElementScope, - AdaptivePaneScope by delegate.paneScope { + PaneScope by delegate.paneScope { @OptIn(ExperimentalSharedTransitionApi::class) override fun movableSharedElementOf( key: Any, @@ -115,9 +120,9 @@ private class ThreePaneMovableSharedElementScope( } } -fun AdaptivePaneState?.canAnimateOnStartingFrames() = +fun PaneState?.canAnimateOnStartingFrames() = this?.pane != ThreePane.TransientPrimary -private val AdaptivePaneScope.isPreviewingBack: Boolean +private val PaneScope.isPreviewingBack: Boolean get() = paneState.pane == ThreePane.Primary && paneState.adaptations.contains(ThreePane.PrimaryToTransient) \ No newline at end of file diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/ThreePaneAdaptiveConfiguration.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/ThreePaneAdaptiveConfiguration.kt index 0a7e883..e3bf630 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/ThreePaneAdaptiveConfiguration.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/ThreePaneAdaptiveConfiguration.kt @@ -4,24 +4,24 @@ import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.AdaptiveNavHostConfiguration -import com.tunjid.treenav.adaptive.adaptivePaneStrategy +import com.tunjid.treenav.adaptive.PanedNavHostConfiguration +import com.tunjid.treenav.adaptive.paneStrategy import com.tunjid.treenav.adaptive.delegated import com.tunjid.treenav.adaptive.threepane.ThreePane /** - * An [AdaptiveNavHostConfiguration] that selectively displays panes for a [ThreePane] layout + * An [PanedNavHostConfiguration] that selectively displays panes for a [ThreePane] layout * based on the space available determined by the [windowWidthDpState]. * * @param windowWidthDpState provides the current width of the display in Dp. */ -fun AdaptiveNavHostConfiguration.threePaneAdaptiveConfiguration( +fun PanedNavHostConfiguration.threePaneAdaptiveConfiguration( windowWidthDpState: State, secondaryPaneBreakPoint: State = mutableStateOf(SECONDARY_PANE_MIN_WIDTH_BREAKPOINT_DP), tertiaryPaneBreakPoint: State = mutableStateOf(TERTIARY_PANE_MIN_WIDTH_BREAKPOINT_DP), -): AdaptiveNavHostConfiguration = delegated { node -> +): PanedNavHostConfiguration = delegated { node -> val originalStrategy = this@threePaneAdaptiveConfiguration.strategyTransform(node) - adaptivePaneStrategy( + paneStrategy( render = originalStrategy.render, transitions = originalStrategy.transitions, paneMapping = { inner -> diff --git a/library/compose/src/commonTest/kotlin/com/tunjid/treenav/adaptive/SlotBasedAdaptiveNavigationStateTest.kt b/library/compose/src/commonTest/kotlin/com/tunjid/treenav/adaptive/SlotBasedAdaptiveNavigationStateTest.kt index d395002..5d05ebb 100644 --- a/library/compose/src/commonTest/kotlin/com/tunjid/treenav/adaptive/SlotBasedAdaptiveNavigationStateTest.kt +++ b/library/compose/src/commonTest/kotlin/com/tunjid/treenav/adaptive/SlotBasedAdaptiveNavigationStateTest.kt @@ -44,7 +44,7 @@ data class TestNode(val name: String) : Node { class SlotBasedAdaptiveNavigationStateTest { - private lateinit var subject: SlotBasedAdaptiveNavigationState + private lateinit var subject: SlotBasedPanedNavigationState private lateinit var panes: List private lateinit var slots: Set @@ -53,7 +53,7 @@ class SlotBasedAdaptiveNavigationStateTest { fun setup() { panes = ThreePane.entries.toList() slots = List(size = panes.size, init = ::Slot).toSet() - subject = SlotBasedAdaptiveNavigationState.initial( + subject = SlotBasedPanedNavigationState.initial( slots = slots ) } @@ -531,7 +531,7 @@ class SlotBasedAdaptiveNavigationStateTest { } } - private fun SlotBasedAdaptiveNavigationState.testAdaptTo( + private fun SlotBasedPanedNavigationState.testAdaptTo( panesToNodes: Map ) = adaptTo( slots = slots, diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt index d367e66..c2adabc 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt @@ -48,14 +48,14 @@ import com.tunjid.demo.common.ui.profile.profileAdaptiveConfiguration import com.tunjid.demo.common.ui.settings.settingsPaneConfiguration import com.tunjid.scaffold.treenav.adaptive.moveablesharedelement.MovableSharedElementHostState import com.tunjid.treenav.MultiStackNav -import com.tunjid.treenav.adaptive.AdaptiveNavHost -import com.tunjid.treenav.adaptive.AdaptiveNavHostConfiguration -import com.tunjid.treenav.adaptive.AdaptivePaneState -import com.tunjid.treenav.adaptive.SavedStateAdaptiveNavHostState -import com.tunjid.treenav.adaptive.adaptiveNavHostConfiguration +import com.tunjid.treenav.adaptive.PanedNavHost +import com.tunjid.treenav.adaptive.PanedNavHostConfiguration +import com.tunjid.treenav.adaptive.PaneState +import com.tunjid.treenav.adaptive.SavedStatePanedNavHostState +import com.tunjid.treenav.adaptive.panedNavHostConfiguration import com.tunjid.treenav.adaptive.threepane.ThreePane import com.tunjid.treenav.adaptive.threepane.configurations.canAnimateOnStartingFrames -import com.tunjid.treenav.adaptive.threepane.configurations.movableSharedElementConfiguration +import com.tunjid.treenav.adaptive.threepane.configurations.threePaneMovableSharedElementConfiguration import com.tunjid.treenav.adaptive.threepane.configurations.threePaneAdaptiveConfiguration import com.tunjid.treenav.current import kotlinx.coroutines.CoroutineScope @@ -86,16 +86,16 @@ fun SampleApp( val movableSharedElementHostState = remember { MovableSharedElementHostState( sharedTransitionScope = this, - canAnimateOnStartingFrames = AdaptivePaneState::canAnimateOnStartingFrames + canAnimateOnStartingFrames = PaneState::canAnimateOnStartingFrames ) } - AdaptiveNavHost( + PanedNavHost( state = appState.rememberAdaptiveNavHostState { this .threePaneAdaptiveConfiguration( windowWidthDpState = windowWidthDp ) - .movableSharedElementConfiguration( + .threePaneMovableSharedElementConfiguration( movableSharedElementHostState = movableSharedElementHostState ) }, @@ -144,21 +144,21 @@ class SampleAppState( ) val currentNavigation by navigationState - private val adaptiveNavHostConfiguration = sampleAppAdaptiveConfiguration( + private val adaptiveNavHostConfiguration = sampleAppNavHostConfiguration( navigationState ) companion object { @Composable fun SampleAppState.rememberAdaptiveNavHostState( - configurationBlock: AdaptiveNavHostConfiguration< + configurationBlock: PanedNavHostConfiguration< ThreePane, MultiStackNav, SampleDestination - >.() -> AdaptiveNavHostConfiguration - ): SavedStateAdaptiveNavHostState { + >.() -> PanedNavHostConfiguration + ): SavedStatePanedNavHostState { val adaptiveNavHostState = remember { - SavedStateAdaptiveNavHostState( + SavedStatePanedNavHostState( panes = ThreePane.entries.toList(), configuration = adaptiveNavHostConfiguration.configurationBlock(), ) @@ -176,9 +176,9 @@ class SampleAppState( } } -private fun sampleAppAdaptiveConfiguration( +private fun sampleAppNavHostConfiguration( multiStackNavState: State -) = adaptiveNavHostConfiguration( +) = panedNavHostConfiguration( navigationState = multiStackNavState, destinationTransform = { multiStackNav -> multiStackNav.current as? SampleDestination ?: throw IllegalArgumentException( diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Configuration.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Configuration.kt index 98455ad..b8ce16a 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Configuration.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Configuration.kt @@ -27,11 +27,11 @@ import com.tunjid.demo.common.ui.data.SampleDestination import com.tunjid.demo.common.ui.data.SampleDestination.NavTabs import com.tunjid.treenav.adaptive.threepane.ThreePane import com.tunjid.treenav.adaptive.threepane.configurations.movableSharedElementScope -import com.tunjid.treenav.adaptive.threepane.threePaneAdaptiveNodeConfiguration +import com.tunjid.treenav.adaptive.threepane.threePaneListDetailAnimationStrategy fun chatAdaptiveConfiguration( destination: SampleDestination.Chat -) = threePaneAdaptiveNodeConfiguration( +) = threePaneListDetailAnimationStrategy( render = { val scope = LocalLifecycleOwner.current.lifecycle.coroutineScope val viewModel = viewModel { diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Configuration.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Configuration.kt index 0dbfdb2..6cb064e 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Configuration.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Configuration.kt @@ -22,10 +22,10 @@ import androidx.lifecycle.coroutineScope import androidx.lifecycle.viewmodel.compose.viewModel import com.tunjid.demo.common.ui.data.ChatsRepository import com.tunjid.demo.common.ui.data.SampleDestination -import com.tunjid.treenav.adaptive.threepane.threePaneAdaptiveNodeConfiguration +import com.tunjid.treenav.adaptive.threepane.threePaneListDetailAnimationStrategy fun chatRoomPaneConfiguration( -) = threePaneAdaptiveNodeConfiguration( +) = threePaneListDetailAnimationStrategy( render = { val scope = LocalLifecycleOwner.current.lifecycle.coroutineScope val viewModel = viewModel { diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Configuration.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Configuration.kt index c69500d..b70b25b 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Configuration.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Configuration.kt @@ -24,11 +24,11 @@ import com.tunjid.demo.common.ui.data.SampleDestination import com.tunjid.demo.common.ui.data.SampleDestination.NavTabs import com.tunjid.treenav.adaptive.threepane.ThreePane import com.tunjid.treenav.adaptive.threepane.configurations.movableSharedElementScope -import com.tunjid.treenav.adaptive.threepane.threePaneAdaptiveNodeConfiguration +import com.tunjid.treenav.adaptive.threepane.threePaneListDetailAnimationStrategy fun profileAdaptiveConfiguration( destination: SampleDestination.Profile -) = threePaneAdaptiveNodeConfiguration( +) = threePaneListDetailAnimationStrategy( render = { val scope = LocalLifecycleOwner.current.lifecycle.coroutineScope val viewModel = viewModel { diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt index 8ecee66..a078a10 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt @@ -17,9 +17,9 @@ package com.tunjid.demo.common.ui.settings import com.tunjid.demo.common.ui.data.SampleDestination -import com.tunjid.treenav.adaptive.threepane.threePaneAdaptiveNodeConfiguration +import com.tunjid.treenav.adaptive.threepane.threePaneListDetailAnimationStrategy fun settingsPaneConfiguration( -) = threePaneAdaptiveNodeConfiguration( +) = threePaneListDetailAnimationStrategy( render = { } ) \ No newline at end of file From fbac257bf8300a127643306981ae67b6bcb9cce8 Mon Sep 17 00:00:00 2001 From: Adetunji Dahunsi Date: Fri, 11 Oct 2024 08:02:06 -0400 Subject: [PATCH 2/5] Better naming --- .../treenav/adaptive/threepane/ThreePane.kt | 6 ++--- .../com/tunjid/demo/common/ui/DemoApp.kt | 16 ++++++------- .../ui/chat/{Configuration.kt => Strategy.kt} | 21 ++++++++-------- .../{Configuration.kt => Strategy.kt} | 6 ++--- .../profile/{Configuration.kt => Strategy.kt} | 24 +++++++++---------- .../demo/common/ui/settings/Configuration.kt | 6 ++--- 6 files changed, 39 insertions(+), 40 deletions(-) rename sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/{Configuration.kt => Strategy.kt} (89%) rename sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/{Configuration.kt => Strategy.kt} (93%) rename sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/{Configuration.kt => Strategy.kt} (87%) diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt index 9f0e6a4..1c54ffb 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt @@ -85,9 +85,9 @@ enum class ThreePane { /** * A strategy for selectively running animations in list detail flows. When: - * * A navigation destination moves between the [ThreePane.Primary] and [ThreePane.Secondary] + * - A navigation destination moves between the [ThreePane.Primary] and [ThreePane.Secondary] * panes, the pane animations are not run to provide a seamless movement experience. - * * A navigation destination moves between the [ThreePane.Primary] and + * - A navigation destination moves between the [ThreePane.Primary] and * [ThreePane.TransientPrimary] panes, the pane animations are not run. * * @param enterTransition the transition to run for the entering pane when permitted. @@ -95,7 +95,7 @@ enum class ThreePane { * @param paneMapping the mapping of panes to navigation destinations. * @param render the Composable for rendering the current destination. */ -fun threePaneListDetailAnimationStrategy( +fun threePaneListDetailStrategy( enterTransition: PaneScope.() -> EnterTransition = { DefaultFadeIn }, exitTransition: PaneScope.() -> ExitTransition = { DefaultFadeOut }, paneMapping: @Composable (R) -> Map = { diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt index c2adabc..4af5377 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt @@ -40,12 +40,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import com.tunjid.demo.common.ui.SampleAppState.Companion.rememberAdaptiveNavHostState -import com.tunjid.demo.common.ui.chat.chatAdaptiveConfiguration -import com.tunjid.demo.common.ui.chatrooms.chatRoomPaneConfiguration +import com.tunjid.demo.common.ui.chat.chatPaneStrategy +import com.tunjid.demo.common.ui.chatrooms.chatRoomPaneStrategy import com.tunjid.demo.common.ui.data.NavigationRepository import com.tunjid.demo.common.ui.data.SampleDestination -import com.tunjid.demo.common.ui.profile.profileAdaptiveConfiguration -import com.tunjid.demo.common.ui.settings.settingsPaneConfiguration +import com.tunjid.demo.common.ui.profile.profilePaneStrategy +import com.tunjid.demo.common.ui.settings.settingsPaneStrategy import com.tunjid.scaffold.treenav.adaptive.moveablesharedelement.MovableSharedElementHostState import com.tunjid.treenav.MultiStackNav import com.tunjid.treenav.adaptive.PanedNavHost @@ -187,13 +187,13 @@ private fun sampleAppNavHostConfiguration( }, strategyTransform = { destination -> when (destination) { - SampleDestination.NavTabs.ChatRooms -> chatRoomPaneConfiguration() + SampleDestination.NavTabs.ChatRooms -> chatRoomPaneStrategy() - is SampleDestination.Chat -> chatAdaptiveConfiguration(destination) + SampleDestination.NavTabs.Settings -> settingsPaneStrategy() - SampleDestination.NavTabs.Settings -> settingsPaneConfiguration() + is SampleDestination.Chat -> chatPaneStrategy() - is SampleDestination.Profile -> profileAdaptiveConfiguration(destination) + is SampleDestination.Profile -> profilePaneStrategy() } } ) diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Configuration.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Strategy.kt similarity index 89% rename from sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Configuration.kt rename to sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Strategy.kt index b8ce16a..961a139 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Configuration.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Strategy.kt @@ -27,12 +27,17 @@ import com.tunjid.demo.common.ui.data.SampleDestination import com.tunjid.demo.common.ui.data.SampleDestination.NavTabs import com.tunjid.treenav.adaptive.threepane.ThreePane import com.tunjid.treenav.adaptive.threepane.configurations.movableSharedElementScope -import com.tunjid.treenav.adaptive.threepane.threePaneListDetailAnimationStrategy +import com.tunjid.treenav.adaptive.threepane.threePaneListDetailStrategy -fun chatAdaptiveConfiguration( - destination: SampleDestination.Chat -) = threePaneListDetailAnimationStrategy( - render = { +fun chatPaneStrategy() = threePaneListDetailStrategy( + paneMapping = { destination -> + mapOf( + ThreePane.Primary to destination, + ThreePane.Secondary to NavTabs.ChatRooms, + ) + }, + render = { destination -> + check(destination is SampleDestination.Chat) val scope = LocalLifecycleOwner.current.lifecycle.coroutineScope val viewModel = viewModel { ChatViewModel( @@ -55,10 +60,4 @@ fun chatAdaptiveConfiguration( ) } }, - paneMapping = { - mapOf( - ThreePane.Primary to it, - ThreePane.Secondary to NavTabs.ChatRooms, - ) - } ) diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Configuration.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Strategy.kt similarity index 93% rename from sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Configuration.kt rename to sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Strategy.kt index 6cb064e..926a318 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Configuration.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Strategy.kt @@ -22,10 +22,10 @@ import androidx.lifecycle.coroutineScope import androidx.lifecycle.viewmodel.compose.viewModel import com.tunjid.demo.common.ui.data.ChatsRepository import com.tunjid.demo.common.ui.data.SampleDestination -import com.tunjid.treenav.adaptive.threepane.threePaneListDetailAnimationStrategy +import com.tunjid.treenav.adaptive.threepane.threePaneListDetailStrategy -fun chatRoomPaneConfiguration( -) = threePaneListDetailAnimationStrategy( +fun chatRoomPaneStrategy( +) = threePaneListDetailStrategy( render = { val scope = LocalLifecycleOwner.current.lifecycle.coroutineScope val viewModel = viewModel { diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Configuration.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt similarity index 87% rename from sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Configuration.kt rename to sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt index b70b25b..a3475c3 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Configuration.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt @@ -24,12 +24,19 @@ import com.tunjid.demo.common.ui.data.SampleDestination import com.tunjid.demo.common.ui.data.SampleDestination.NavTabs import com.tunjid.treenav.adaptive.threepane.ThreePane import com.tunjid.treenav.adaptive.threepane.configurations.movableSharedElementScope -import com.tunjid.treenav.adaptive.threepane.threePaneListDetailAnimationStrategy +import com.tunjid.treenav.adaptive.threepane.threePaneListDetailStrategy -fun profileAdaptiveConfiguration( - destination: SampleDestination.Profile -) = threePaneListDetailAnimationStrategy( - render = { +fun profilePaneStrategy() = threePaneListDetailStrategy( + paneMapping = { destination -> + check(destination is SampleDestination.Profile) + mapOf( + ThreePane.Primary to destination, + ThreePane.Secondary to destination.roomName?.let(SampleDestination::Chat), + ThreePane.Tertiary to destination.roomName?.let { NavTabs.ChatRooms }, + ) + }, + render = { destination -> + check(destination is SampleDestination.Profile) val scope = LocalLifecycleOwner.current.lifecycle.coroutineScope val viewModel = viewModel { ProfileViewModel( @@ -43,11 +50,4 @@ fun profileAdaptiveConfiguration( onAction = viewModel.accept ) }, - paneMapping = { - mapOf( - ThreePane.Primary to destination, - ThreePane.Secondary to destination.roomName?.let(SampleDestination::Chat), - ThreePane.Tertiary to destination.roomName?.let { NavTabs.ChatRooms }, - ) - } ) \ No newline at end of file diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt index a078a10..5ed820b 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt @@ -17,9 +17,9 @@ package com.tunjid.demo.common.ui.settings import com.tunjid.demo.common.ui.data.SampleDestination -import com.tunjid.treenav.adaptive.threepane.threePaneListDetailAnimationStrategy +import com.tunjid.treenav.adaptive.threepane.threePaneListDetailStrategy -fun settingsPaneConfiguration( -) = threePaneListDetailAnimationStrategy( +fun settingsPaneStrategy( +) = threePaneListDetailStrategy( render = { } ) \ No newline at end of file From 0605f441817afeddda191b0d71e2fe9a0eae8f48 Mon Sep 17 00:00:00 2001 From: Adetunji Dahunsi Date: Fri, 11 Oct 2024 08:14:51 -0400 Subject: [PATCH 3/5] Add navigation for me tab --- .../com/tunjid/demo/common/ui/DemoApp.kt | 12 +++-- .../common/ui/data/NavigationRepository.kt | 13 ++++-- .../com/tunjid/demo/common/ui/me/Strategy.kt | 45 +++++++++++++++++++ .../demo/common/ui/profile/ProfileScreen.kt | 11 +++-- .../common/ui/profile/ProfileViewModel.kt | 12 ++--- .../tunjid/demo/common/ui/profile/Strategy.kt | 2 +- .../demo/common/ui/settings/Configuration.kt | 25 ----------- 7 files changed, 78 insertions(+), 42 deletions(-) create mode 100644 sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/me/Strategy.kt delete mode 100644 sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt index 4af5377..d3f9065 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt @@ -45,7 +45,7 @@ import com.tunjid.demo.common.ui.chatrooms.chatRoomPaneStrategy import com.tunjid.demo.common.ui.data.NavigationRepository import com.tunjid.demo.common.ui.data.SampleDestination import com.tunjid.demo.common.ui.profile.profilePaneStrategy -import com.tunjid.demo.common.ui.settings.settingsPaneStrategy +import com.tunjid.demo.common.ui.me.mePaneStrategy import com.tunjid.scaffold.treenav.adaptive.moveablesharedelement.MovableSharedElementHostState import com.tunjid.treenav.MultiStackNav import com.tunjid.treenav.adaptive.PanedNavHost @@ -75,7 +75,7 @@ fun SampleApp( icon = { Icon(it.icon, contentDescription = it.title) }, label = { Text(it.title) }, selected = it == appState.currentNavigation.current, - onClick = { } + onClick = { appState.setTab(it) } ) } } @@ -148,6 +148,12 @@ class SampleAppState( navigationState ) + fun setTab(destination: SampleDestination.NavTabs) { + navigationRepository.navigate { + it.copy(currentIndex = destination.ordinal) + } + } + companion object { @Composable fun SampleAppState.rememberAdaptiveNavHostState( @@ -189,7 +195,7 @@ private fun sampleAppNavHostConfiguration( when (destination) { SampleDestination.NavTabs.ChatRooms -> chatRoomPaneStrategy() - SampleDestination.NavTabs.Settings -> settingsPaneStrategy() + SampleDestination.NavTabs.Me -> mePaneStrategy() is SampleDestination.Chat -> chatPaneStrategy() diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/data/NavigationRepository.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/data/NavigationRepository.kt index 6cc1e51..1e29e27 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/data/NavigationRepository.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/data/NavigationRepository.kt @@ -18,6 +18,7 @@ package com.tunjid.demo.common.ui.data import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.List +import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Settings import com.tunjid.mutator.Mutation import com.tunjid.mutator.coroutines.mapToManyMutations @@ -36,14 +37,14 @@ sealed interface SampleDestination : Node { val title: String, ) : SampleDestination { ChatRooms("Chat Rooms"), - Settings("Settings"); + Me("Me"); override val id: String get() = title val icon get() = when (this) { ChatRooms -> Icons.AutoMirrored.Filled.List - Settings -> Icons.Default.Settings + Me -> Icons.Default.Person } } @@ -107,6 +108,12 @@ private val InitialNavState = MultiStackNav( children = listOf( SampleDestination.NavTabs.ChatRooms, ) - ) + ), + StackNav( + name = "me", + children = listOf( + SampleDestination.NavTabs.Me, + ) + ), ) ) \ No newline at end of file diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/me/Strategy.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/me/Strategy.kt new file mode 100644 index 0000000..b9acbc9 --- /dev/null +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/me/Strategy.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.tunjid.demo.common.ui.me + +import androidx.lifecycle.compose.LocalLifecycleOwner +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.coroutineScope +import androidx.lifecycle.viewmodel.compose.viewModel +import com.tunjid.demo.common.ui.data.SampleDestination +import com.tunjid.demo.common.ui.profile.ProfileScreen +import com.tunjid.demo.common.ui.profile.ProfileViewModel +import com.tunjid.treenav.adaptive.threepane.configurations.movableSharedElementScope +import com.tunjid.treenav.adaptive.threepane.threePaneListDetailStrategy + +fun mePaneStrategy( +) = threePaneListDetailStrategy( + render = { + val scope = LocalLifecycleOwner.current.lifecycle.coroutineScope + val viewModel = viewModel { + ProfileViewModel( + coroutineScope = scope, + profileName = null, + ) + } + ProfileScreen( + movableSharedElementScope = movableSharedElementScope(), + state = viewModel.state.collectAsStateWithLifecycle().value, + onAction = viewModel.accept + ) + } +) \ No newline at end of file diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileScreen.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileScreen.kt index 19ff986..de9937d 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileScreen.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileScreen.kt @@ -30,6 +30,7 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.text.font.FontWeight @@ -57,8 +58,10 @@ fun ProfileScreen( ProfileHeader( state = state, movableSharedElementScope = movableSharedElementScope, - onBackPressed = { - onAction(Action.Navigation.Pop) + onBackPressed = remember(state.profileName) { + if (state.profileName != null) return@remember { + onAction(Action.Navigation.Pop) + } else null }, modifier = Modifier .fillMaxWidth() @@ -82,7 +85,7 @@ private fun ProfileHeader( state: State, movableSharedElementScope: MovableSharedElementScope, modifier: Modifier = Modifier, - onBackPressed: () -> Unit + onBackPressed: (() -> Unit)?, ) { Box { Box( @@ -95,7 +98,7 @@ private fun ProfileHeader( ) } SampleTopAppBar( - title = "Profile", + title = if (state.profileName == null) "Me" else "Profile", onBackPressed = onBackPressed, ) } diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileViewModel.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileViewModel.kt index b7345d1..2a6788a 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileViewModel.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileViewModel.kt @@ -22,7 +22,6 @@ import com.tunjid.demo.common.ui.data.NavigationAction import com.tunjid.demo.common.ui.data.NavigationRepository import com.tunjid.demo.common.ui.data.Profile import com.tunjid.demo.common.ui.data.ProfileRepository -import com.tunjid.demo.common.ui.data.SampleDestination import com.tunjid.demo.common.ui.data.navigationAction import com.tunjid.demo.common.ui.data.navigationMutations import com.tunjid.mutator.Mutation @@ -37,14 +36,14 @@ class ProfileViewModel( coroutineScope: LifecycleCoroutineScope, profileRepository: ProfileRepository = ProfileRepository, navigationRepository: NavigationRepository = NavigationRepository, - destination: SampleDestination.Profile, + profileName: String?, ) : ViewModel() { private val mutator = coroutineScope.actionStateFlowMutator( initialState = State( - profileName = destination.profileName + profileName = profileName ), inputs = listOf( - profileRepository.profileMutations(destination) + profileRepository.profileMutations(profileName) ), actionTransform = { actions -> actions.toMutationStream( @@ -65,9 +64,10 @@ class ProfileViewModel( } private fun ProfileRepository.profileMutations( - destination: SampleDestination.Profile, + profileName: String?, ): Flow> = - profileFor(destination.profileName).mapToMutation { copy(profile = it) } + (profileName?.let(::profileFor) ?: me) + .mapToMutation { copy(profile = it) } data class State( val profileName: String? = null, diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt index a3475c3..02256b1 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt @@ -41,7 +41,7 @@ fun profilePaneStrategy() = threePaneListDetailStrategy( val viewModel = viewModel { ProfileViewModel( coroutineScope = scope, - destination = destination, + profileName = destination.profileName, ) } ProfileScreen( diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt deleted file mode 100644 index 5ed820b..0000000 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/settings/Configuration.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.tunjid.demo.common.ui.settings - -import com.tunjid.demo.common.ui.data.SampleDestination -import com.tunjid.treenav.adaptive.threepane.threePaneListDetailStrategy - -fun settingsPaneStrategy( -) = threePaneListDetailStrategy( - render = { } -) \ No newline at end of file From fa3118b621b61b022f6badacf0a7d4a253db94df Mon Sep 17 00:00:00 2001 From: Adetunji Dahunsi Date: Fri, 11 Oct 2024 21:42:02 -0400 Subject: [PATCH 4/5] Fix issue with collapsing toolbar stating out collapsed bc of movable shared element --- gradle/libs.versions.toml | 2 +- .../demo/common/ui/profile/ProfileScreen.kt | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cd44b37..106f139 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,7 @@ kotlinxCoroutines = "1.9.0" kotlinxDatetime = "0.6.1" lifecycle-runtime = "2.8.6" tunjidStateHolder = "1.1.0" -tunjidComposables = "0.0.4" +tunjidComposables = "0.0.5" junit = "4.13.2" runner = "1.0.2" espressoCore = "3.0.2" diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileScreen.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileScreen.kt index de9937d..61a91c3 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileScreen.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/ProfileScreen.kt @@ -20,9 +20,9 @@ import androidx.compose.animation.ExperimentalSharedTransitionApi import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState @@ -87,16 +87,14 @@ private fun ProfileHeader( modifier: Modifier = Modifier, onBackPressed: (() -> Unit)?, ) { - Box { - Box( + Box( + modifier = Modifier.heightIn(min = 400.dp) + ) { + ProfilePhoto( + state = state, + movableSharedElementScope = movableSharedElementScope, modifier = modifier - ) { - ProfilePhoto( - state = state, - movableSharedElementScope = movableSharedElementScope, - modifier = Modifier.fillMaxSize() - ) - } + ) SampleTopAppBar( title = if (state.profileName == null) "Me" else "Profile", onBackPressed = onBackPressed, From 406e1c149dadb2dc1e12350577b413242026a792 Mon Sep 17 00:00:00 2001 From: Adetunji Dahunsi Date: Sat, 12 Oct 2024 08:20:39 -0400 Subject: [PATCH 5/5] Update package names --- .../{adaptive => compose}/PaneScope.kt | 2 +- .../{adaptive => compose}/PaneStrategy.kt | 2 +- .../{adaptive => compose}/PanedNavHost.kt | 2 +- .../PanedNavHostConfiguration.kt | 22 +++++++++++---- .../PanedNavigationState.kt | 2 +- .../SavedStatePanedNavHostState.kt | 6 ++-- .../SlotBasedPanedNavigationState.kt | 4 +-- .../lifecycle/DestinationLifecycleOwner.kt | 6 ++-- .../DestinationViewModelStoreCreator.kt | 2 +- .../BoundsTransformDeferredAnimation.kt | 2 +- .../MovableSharedElementState.kt | 5 ++-- .../MovableSharedElements.kt | 6 ++-- .../threepane/ThreePane.kt | 10 +++---- .../MovableSharedElementConfiguration.kt | 20 ++++++------- .../ThreePaneAdaptiveConfiguration.kt | 18 +++++++----- .../SlotBasedAdaptiveNavigationStateTest.kt | 4 +-- .../com/tunjid/demo/common/ui/DemoApp.kt | 28 +++++++++---------- .../tunjid/demo/common/ui/chat/Strategy.kt | 6 ++-- .../demo/common/ui/chatrooms/Strategy.kt | 2 +- .../com/tunjid/demo/common/ui/me/Strategy.kt | 4 +-- .../tunjid/demo/common/ui/profile/Strategy.kt | 6 ++-- 21 files changed, 88 insertions(+), 71 deletions(-) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/PaneScope.kt (98%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/PaneStrategy.kt (97%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/PanedNavHost.kt (97%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/PanedNavHostConfiguration.kt (93%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/PanedNavigationState.kt (97%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/SavedStatePanedNavHostState.kt (98%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/SlotBasedPanedNavigationState.kt (98%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/lifecycle/DestinationLifecycleOwner.kt (91%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/lifecycle/DestinationViewModelStoreCreator.kt (97%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/moveablesharedelement/BoundsTransformDeferredAnimation.kt (99%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/moveablesharedelement/MovableSharedElementState.kt (98%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/moveablesharedelement/MovableSharedElements.kt (97%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/threepane/ThreePane.kt (95%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/threepane/configurations/MovableSharedElementConfiguration.kt (90%) rename library/compose/src/commonMain/kotlin/com/tunjid/treenav/{adaptive => compose}/threepane/configurations/ThreePaneAdaptiveConfiguration.kt (81%) rename library/compose/src/commonTest/kotlin/com/tunjid/treenav/{adaptive => compose}/SlotBasedAdaptiveNavigationStateTest.kt (99%) diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneScope.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PaneScope.kt similarity index 98% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneScope.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PaneScope.kt index afe7f52..57ffe05 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneScope.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PaneScope.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.tunjid.treenav.adaptive +package com.tunjid.treenav.compose import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.AnimatedVisibilityScope diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneStrategy.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PaneStrategy.kt similarity index 97% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneStrategy.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PaneStrategy.kt index 4dbcefa..937e043 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PaneStrategy.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PaneStrategy.kt @@ -1,4 +1,4 @@ -package com.tunjid.treenav.adaptive +package com.tunjid.treenav.compose import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHost.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PanedNavHost.kt similarity index 97% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHost.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PanedNavHost.kt index 2b9fa73..ab83491 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHost.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PanedNavHost.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.tunjid.treenav.adaptive +package com.tunjid.treenav.compose import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHostConfiguration.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PanedNavHostConfiguration.kt similarity index 93% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHostConfiguration.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PanedNavHostConfiguration.kt index d656df9..856e335 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavHostConfiguration.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PanedNavHostConfiguration.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.tunjid.treenav.adaptive +package com.tunjid.treenav.compose import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable @@ -77,7 +77,11 @@ fun panedNavHostConfiguration * @param strategyTransform provides the strategy used to adapt the current destination to the * panes available. */ -fun PanedNavHostConfiguration.delegated( +fun PanedNavHostConfiguration< + Pane, + NavigationState, + Destination + >.delegated( destinationTransform: (NavigationState) -> Destination = this@delegated.destinationTransform, strategyTransform: (destination: Destination) -> PaneStrategy ) = panedNavHostConfiguration( @@ -90,7 +94,11 @@ fun PanedNavHostConfiguration * The current destination in a given [paneScope]. */ @Composable -internal fun PanedNavHostConfiguration.Destination( +internal fun PanedNavHostConfiguration< + Pane, + *, + Destination + >.Destination( paneScope: PaneScope ) { val current = remember(paneScope.paneState.currentDestination) { @@ -105,7 +113,7 @@ internal fun PanedNavHostConfiguration PanedNavHostConfiguration PanedNavHostConfiguration.paneMapping(): Map { +internal fun PanedNavHostConfiguration< + Pane, + *, + Destination + >.paneMapping(): Map { val current by currentDestination return current.let { strategyTransform(it).paneMapper(it) diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavigationState.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PanedNavigationState.kt similarity index 97% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavigationState.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PanedNavigationState.kt index 6beabe1..c8bd66d 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/PanedNavigationState.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/PanedNavigationState.kt @@ -1,4 +1,4 @@ -package com.tunjid.treenav.adaptive +package com.tunjid.treenav.compose import com.tunjid.treenav.Node diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SavedStatePanedNavHostState.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/SavedStatePanedNavHostState.kt similarity index 98% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SavedStatePanedNavHostState.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/SavedStatePanedNavHostState.kt index 4136ab5..d1e88c7 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SavedStatePanedNavHostState.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/SavedStatePanedNavHostState.kt @@ -1,4 +1,4 @@ -package com.tunjid.treenav.adaptive +package com.tunjid.treenav.compose import androidx.compose.animation.AnimatedContent import androidx.compose.animation.ContentTransform @@ -25,8 +25,8 @@ import androidx.lifecycle.compose.currentStateAsState import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner import com.tunjid.treenav.Node import com.tunjid.treenav.Order -import com.tunjid.treenav.adaptive.lifecycle.DestinationViewModelStoreCreator -import com.tunjid.treenav.adaptive.lifecycle.rememberDestinationLifecycleOwner +import com.tunjid.treenav.compose.lifecycle.DestinationViewModelStoreCreator +import com.tunjid.treenav.compose.lifecycle.rememberDestinationLifecycleOwner import com.tunjid.treenav.traverse diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SlotBasedPanedNavigationState.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/SlotBasedPanedNavigationState.kt similarity index 98% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SlotBasedPanedNavigationState.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/SlotBasedPanedNavigationState.kt index f1efd84..b2a548a 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/SlotBasedPanedNavigationState.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/SlotBasedPanedNavigationState.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.tunjid.treenav.adaptive +package com.tunjid.treenav.compose import androidx.compose.runtime.Immutable import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.Adaptation.Change.contains +import com.tunjid.treenav.compose.Adaptation.Change.contains /** * Data structure for managing navigation as it adapts to various layout configurations diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/lifecycle/DestinationLifecycleOwner.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/lifecycle/DestinationLifecycleOwner.kt similarity index 91% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/lifecycle/DestinationLifecycleOwner.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/lifecycle/DestinationLifecycleOwner.kt index 010de17..16e2a2a 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/lifecycle/DestinationLifecycleOwner.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/lifecycle/DestinationLifecycleOwner.kt @@ -1,4 +1,4 @@ -package com.tunjid.treenav.adaptive.lifecycle +package com.tunjid.treenav.compose.lifecycle import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable @@ -9,8 +9,8 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import androidx.lifecycle.compose.LocalLifecycleOwner import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.PaneScope -import com.tunjid.treenav.adaptive.SlotBasedPanedNavigationState +import com.tunjid.treenav.compose.PaneScope +import com.tunjid.treenav.compose.SlotBasedPanedNavigationState @Composable internal fun rememberDestinationLifecycleOwner( diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/lifecycle/DestinationViewModelStoreCreator.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/lifecycle/DestinationViewModelStoreCreator.kt similarity index 97% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/lifecycle/DestinationViewModelStoreCreator.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/lifecycle/DestinationViewModelStoreCreator.kt index 596073a..b18205f 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/lifecycle/DestinationViewModelStoreCreator.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/lifecycle/DestinationViewModelStoreCreator.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.tunjid.treenav.adaptive.lifecycle +package com.tunjid.treenav.compose.lifecycle import androidx.compose.runtime.Stable import androidx.lifecycle.ViewModelStore diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/BoundsTransformDeferredAnimation.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/moveablesharedelement/BoundsTransformDeferredAnimation.kt similarity index 99% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/BoundsTransformDeferredAnimation.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/moveablesharedelement/BoundsTransformDeferredAnimation.kt index 0902923..09b1c8e 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/BoundsTransformDeferredAnimation.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/moveablesharedelement/BoundsTransformDeferredAnimation.kt @@ -1,4 +1,4 @@ -package com.tunjid.scaffold.treenav.adaptive.moveablesharedelement +package com.tunjid.treenav.compose.moveablesharedelement import androidx.compose.animation.BoundsTransform diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElementState.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/moveablesharedelement/MovableSharedElementState.kt similarity index 98% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElementState.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/moveablesharedelement/MovableSharedElementState.kt index 9177310..9e97c2b 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElementState.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/moveablesharedelement/MovableSharedElementState.kt @@ -34,8 +34,9 @@ import androidx.compose.ui.unit.toOffset import androidx.compose.ui.unit.toSize import androidx.compose.ui.util.fastRoundToInt import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.PaneScope -import com.tunjid.treenav.adaptive.PaneState +import com.tunjid.treenav.compose.PaneScope +import com.tunjid.treenav.compose.PaneState +import com.tunjid.treenav.compose.moveablesharedelement.BoundsTransformDeferredAnimation import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.first diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElements.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/moveablesharedelement/MovableSharedElements.kt similarity index 97% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElements.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/moveablesharedelement/MovableSharedElements.kt index f8eae96..8ca6fc3 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/moveablesharedelement/MovableSharedElements.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/moveablesharedelement/MovableSharedElements.kt @@ -17,9 +17,9 @@ import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.drawscope.ContentDrawScope import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.PanedNavHost -import com.tunjid.treenav.adaptive.PaneScope -import com.tunjid.treenav.adaptive.PaneState +import com.tunjid.treenav.compose.PanedNavHost +import com.tunjid.treenav.compose.PaneScope +import com.tunjid.treenav.compose.PaneState internal interface SharedElementOverlay { fun ContentDrawScope.drawInOverlay() diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/threepane/ThreePane.kt similarity index 95% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/threepane/ThreePane.kt index 1c54ffb..28349c4 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/ThreePane.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/threepane/ThreePane.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.tunjid.treenav.adaptive.threepane +package com.tunjid.treenav.compose.threepane import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition @@ -24,10 +24,10 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.runtime.Composable import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.Adaptation.Swap -import com.tunjid.treenav.adaptive.PaneScope -import com.tunjid.treenav.adaptive.PaneStrategy -import com.tunjid.treenav.adaptive.paneStrategy +import com.tunjid.treenav.compose.Adaptation.Swap +import com.tunjid.treenav.compose.PaneScope +import com.tunjid.treenav.compose.PaneStrategy +import com.tunjid.treenav.compose.paneStrategy /** * A [PaneStrategy] for apps that display up to 3 major panes as once. diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/MovableSharedElementConfiguration.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/threepane/configurations/MovableSharedElementConfiguration.kt similarity index 90% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/MovableSharedElementConfiguration.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/threepane/configurations/MovableSharedElementConfiguration.kt index 9117af2..ad63802 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/MovableSharedElementConfiguration.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/threepane/configurations/MovableSharedElementConfiguration.kt @@ -1,4 +1,4 @@ -package com.tunjid.treenav.adaptive.threepane.configurations +package com.tunjid.treenav.compose.threepane.configurations import androidx.compose.animation.BoundsTransform import androidx.compose.animation.ExperimentalSharedTransitionApi @@ -11,13 +11,13 @@ import com.tunjid.scaffold.treenav.adaptive.moveablesharedelement.AdaptiveMovabl import com.tunjid.scaffold.treenav.adaptive.moveablesharedelement.MovableSharedElementHostState import com.tunjid.scaffold.treenav.adaptive.moveablesharedelement.MovableSharedElementScope import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.PanedNavHost -import com.tunjid.treenav.adaptive.PanedNavHostConfiguration -import com.tunjid.treenav.adaptive.PaneScope -import com.tunjid.treenav.adaptive.PaneState -import com.tunjid.treenav.adaptive.PaneStrategy -import com.tunjid.treenav.adaptive.delegated -import com.tunjid.treenav.adaptive.threepane.ThreePane +import com.tunjid.treenav.compose.PanedNavHost +import com.tunjid.treenav.compose.PanedNavHostConfiguration +import com.tunjid.treenav.compose.PaneScope +import com.tunjid.treenav.compose.PaneState +import com.tunjid.treenav.compose.PaneStrategy +import com.tunjid.treenav.compose.delegated +import com.tunjid.treenav.compose.threepane.ThreePane /** @@ -31,12 +31,12 @@ fun PanedNavHostConfiguration< ThreePane, NavigationState, Destination - >.threePaneMovableSharedElementConfiguration( + >.threePanedMovableSharedElementConfiguration( movableSharedElementHostState: MovableSharedElementHostState, ): PanedNavHostConfiguration = delegated { destination -> val originalStrategy = - this@threePaneMovableSharedElementConfiguration.strategyTransform(destination) + this@threePanedMovableSharedElementConfiguration.strategyTransform(destination) PaneStrategy( transitions = originalStrategy.transitions, paneMapper = originalStrategy.paneMapper, diff --git a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/ThreePaneAdaptiveConfiguration.kt b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/threepane/configurations/ThreePaneAdaptiveConfiguration.kt similarity index 81% rename from library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/ThreePaneAdaptiveConfiguration.kt rename to library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/threepane/configurations/ThreePaneAdaptiveConfiguration.kt index e3bf630..4960c44 100644 --- a/library/compose/src/commonMain/kotlin/com/tunjid/treenav/adaptive/threepane/configurations/ThreePaneAdaptiveConfiguration.kt +++ b/library/compose/src/commonMain/kotlin/com/tunjid/treenav/compose/threepane/configurations/ThreePaneAdaptiveConfiguration.kt @@ -1,13 +1,13 @@ -package com.tunjid.treenav.adaptive.threepane.configurations +package com.tunjid.treenav.compose.threepane.configurations import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.PanedNavHostConfiguration -import com.tunjid.treenav.adaptive.paneStrategy -import com.tunjid.treenav.adaptive.delegated -import com.tunjid.treenav.adaptive.threepane.ThreePane +import com.tunjid.treenav.compose.PanedNavHostConfiguration +import com.tunjid.treenav.compose.paneStrategy +import com.tunjid.treenav.compose.delegated +import com.tunjid.treenav.compose.threepane.ThreePane /** * An [PanedNavHostConfiguration] that selectively displays panes for a [ThreePane] layout @@ -15,12 +15,16 @@ import com.tunjid.treenav.adaptive.threepane.ThreePane * * @param windowWidthDpState provides the current width of the display in Dp. */ -fun PanedNavHostConfiguration.threePaneAdaptiveConfiguration( +fun PanedNavHostConfiguration< + ThreePane, + NavigationState, + Destination + >.threePanedNavHostConfiguration( windowWidthDpState: State, secondaryPaneBreakPoint: State = mutableStateOf(SECONDARY_PANE_MIN_WIDTH_BREAKPOINT_DP), tertiaryPaneBreakPoint: State = mutableStateOf(TERTIARY_PANE_MIN_WIDTH_BREAKPOINT_DP), ): PanedNavHostConfiguration = delegated { node -> - val originalStrategy = this@threePaneAdaptiveConfiguration.strategyTransform(node) + val originalStrategy = this@threePanedNavHostConfiguration.strategyTransform(node) paneStrategy( render = originalStrategy.render, transitions = originalStrategy.transitions, diff --git a/library/compose/src/commonTest/kotlin/com/tunjid/treenav/adaptive/SlotBasedAdaptiveNavigationStateTest.kt b/library/compose/src/commonTest/kotlin/com/tunjid/treenav/compose/SlotBasedAdaptiveNavigationStateTest.kt similarity index 99% rename from library/compose/src/commonTest/kotlin/com/tunjid/treenav/adaptive/SlotBasedAdaptiveNavigationStateTest.kt rename to library/compose/src/commonTest/kotlin/com/tunjid/treenav/compose/SlotBasedAdaptiveNavigationStateTest.kt index 5d05ebb..f2236f7 100644 --- a/library/compose/src/commonTest/kotlin/com/tunjid/treenav/adaptive/SlotBasedAdaptiveNavigationStateTest.kt +++ b/library/compose/src/commonTest/kotlin/com/tunjid/treenav/compose/SlotBasedAdaptiveNavigationStateTest.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.tunjid.treenav.adaptive +package com.tunjid.treenav.compose import com.tunjid.treenav.Node -import com.tunjid.treenav.adaptive.threepane.ThreePane +import com.tunjid.treenav.compose.threepane.ThreePane import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt index d3f9065..4b2e0e0 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/DemoApp.kt @@ -39,7 +39,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity -import com.tunjid.demo.common.ui.SampleAppState.Companion.rememberAdaptiveNavHostState +import com.tunjid.demo.common.ui.SampleAppState.Companion.rememberPanedNavHostState import com.tunjid.demo.common.ui.chat.chatPaneStrategy import com.tunjid.demo.common.ui.chatrooms.chatRoomPaneStrategy import com.tunjid.demo.common.ui.data.NavigationRepository @@ -48,15 +48,15 @@ import com.tunjid.demo.common.ui.profile.profilePaneStrategy import com.tunjid.demo.common.ui.me.mePaneStrategy import com.tunjid.scaffold.treenav.adaptive.moveablesharedelement.MovableSharedElementHostState import com.tunjid.treenav.MultiStackNav -import com.tunjid.treenav.adaptive.PanedNavHost -import com.tunjid.treenav.adaptive.PanedNavHostConfiguration -import com.tunjid.treenav.adaptive.PaneState -import com.tunjid.treenav.adaptive.SavedStatePanedNavHostState -import com.tunjid.treenav.adaptive.panedNavHostConfiguration -import com.tunjid.treenav.adaptive.threepane.ThreePane -import com.tunjid.treenav.adaptive.threepane.configurations.canAnimateOnStartingFrames -import com.tunjid.treenav.adaptive.threepane.configurations.threePaneMovableSharedElementConfiguration -import com.tunjid.treenav.adaptive.threepane.configurations.threePaneAdaptiveConfiguration +import com.tunjid.treenav.compose.PanedNavHost +import com.tunjid.treenav.compose.PanedNavHostConfiguration +import com.tunjid.treenav.compose.PaneState +import com.tunjid.treenav.compose.SavedStatePanedNavHostState +import com.tunjid.treenav.compose.panedNavHostConfiguration +import com.tunjid.treenav.compose.threepane.ThreePane +import com.tunjid.treenav.compose.threepane.configurations.canAnimateOnStartingFrames +import com.tunjid.treenav.compose.threepane.configurations.threePanedMovableSharedElementConfiguration +import com.tunjid.treenav.compose.threepane.configurations.threePanedNavHostConfiguration import com.tunjid.treenav.current import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -90,12 +90,12 @@ fun SampleApp( ) } PanedNavHost( - state = appState.rememberAdaptiveNavHostState { + state = appState.rememberPanedNavHostState { this - .threePaneAdaptiveConfiguration( + .threePanedNavHostConfiguration( windowWidthDpState = windowWidthDp ) - .threePaneMovableSharedElementConfiguration( + .threePanedMovableSharedElementConfiguration( movableSharedElementHostState = movableSharedElementHostState ) }, @@ -156,7 +156,7 @@ class SampleAppState( companion object { @Composable - fun SampleAppState.rememberAdaptiveNavHostState( + fun SampleAppState.rememberPanedNavHostState( configurationBlock: PanedNavHostConfiguration< ThreePane, MultiStackNav, diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Strategy.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Strategy.kt index 961a139..74ea0a2 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Strategy.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chat/Strategy.kt @@ -25,9 +25,9 @@ import com.tunjid.demo.common.ui.data.ChatsRepository import com.tunjid.demo.common.ui.data.ProfileRepository import com.tunjid.demo.common.ui.data.SampleDestination import com.tunjid.demo.common.ui.data.SampleDestination.NavTabs -import com.tunjid.treenav.adaptive.threepane.ThreePane -import com.tunjid.treenav.adaptive.threepane.configurations.movableSharedElementScope -import com.tunjid.treenav.adaptive.threepane.threePaneListDetailStrategy +import com.tunjid.treenav.compose.threepane.ThreePane +import com.tunjid.treenav.compose.threepane.configurations.movableSharedElementScope +import com.tunjid.treenav.compose.threepane.threePaneListDetailStrategy fun chatPaneStrategy() = threePaneListDetailStrategy( paneMapping = { destination -> diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Strategy.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Strategy.kt index 926a318..bc4aa7f 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Strategy.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/chatrooms/Strategy.kt @@ -22,7 +22,7 @@ import androidx.lifecycle.coroutineScope import androidx.lifecycle.viewmodel.compose.viewModel import com.tunjid.demo.common.ui.data.ChatsRepository import com.tunjid.demo.common.ui.data.SampleDestination -import com.tunjid.treenav.adaptive.threepane.threePaneListDetailStrategy +import com.tunjid.treenav.compose.threepane.threePaneListDetailStrategy fun chatRoomPaneStrategy( ) = threePaneListDetailStrategy( diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/me/Strategy.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/me/Strategy.kt index b9acbc9..fed9a3f 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/me/Strategy.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/me/Strategy.kt @@ -23,8 +23,8 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.tunjid.demo.common.ui.data.SampleDestination import com.tunjid.demo.common.ui.profile.ProfileScreen import com.tunjid.demo.common.ui.profile.ProfileViewModel -import com.tunjid.treenav.adaptive.threepane.configurations.movableSharedElementScope -import com.tunjid.treenav.adaptive.threepane.threePaneListDetailStrategy +import com.tunjid.treenav.compose.threepane.configurations.movableSharedElementScope +import com.tunjid.treenav.compose.threepane.threePaneListDetailStrategy fun mePaneStrategy( ) = threePaneListDetailStrategy( diff --git a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt index 02256b1..1780f64 100644 --- a/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt +++ b/sample/common/src/commonMain/kotlin/com/tunjid/demo/common/ui/profile/Strategy.kt @@ -22,9 +22,9 @@ import androidx.lifecycle.coroutineScope import androidx.lifecycle.viewmodel.compose.viewModel import com.tunjid.demo.common.ui.data.SampleDestination import com.tunjid.demo.common.ui.data.SampleDestination.NavTabs -import com.tunjid.treenav.adaptive.threepane.ThreePane -import com.tunjid.treenav.adaptive.threepane.configurations.movableSharedElementScope -import com.tunjid.treenav.adaptive.threepane.threePaneListDetailStrategy +import com.tunjid.treenav.compose.threepane.ThreePane +import com.tunjid.treenav.compose.threepane.configurations.movableSharedElementScope +import com.tunjid.treenav.compose.threepane.threePaneListDetailStrategy fun profilePaneStrategy() = threePaneListDetailStrategy( paneMapping = { destination ->