Skip to content

Commit

Permalink
feat: support setting a Navigator key
Browse files Browse the repository at this point in the history
  • Loading branch information
DevSrSouza committed May 7, 2023
1 parent d747f16 commit df87d6e
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 6 deletions.
Expand Up @@ -3,6 +3,7 @@ package cafe.adriel.voyager.navigator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.currentCompositeKeyHash
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -51,12 +52,14 @@ public fun Navigator(
screen: Screen,
disposeBehavior: NavigatorDisposeBehavior = NavigatorDisposeBehavior(),
onBackPressed: OnBackPressed = { true },
key: String = compositionUniqueId(),
content: NavigatorContent = { CurrentScreen() }
) {
Navigator(
screens = listOf(screen),
disposeBehavior = disposeBehavior,
onBackPressed = onBackPressed,
key = key,
content = content,
)
}
Expand All @@ -66,14 +69,16 @@ public fun Navigator(
screens: List<Screen>,
disposeBehavior: NavigatorDisposeBehavior = NavigatorDisposeBehavior(),
onBackPressed: OnBackPressed = { true },
key: String = compositionUniqueId(),
content: NavigatorContent = { CurrentScreen() },
) {
require(screens.isNotEmpty()) { "Navigator must have at least one screen" }
require(key.isNotEmpty()) { "Navigator key can't be empty" }

CompositionLocalProvider(
LocalNavigatorStateHolder providesDefault rememberSaveableStateHolder()
) {
val navigator = rememberNavigator(screens, disposeBehavior, LocalNavigator.current)
val navigator = rememberNavigator(screens, key, disposeBehavior, LocalNavigator.current)

if (navigator.parent?.disposeBehavior?.disposeNestedNavigators != false) {
NavigatorDisposableEffect(navigator)
Expand All @@ -95,6 +100,7 @@ public fun Navigator(

public class Navigator @InternalVoyagerApi constructor(
screens: List<Screen>,
@InternalVoyagerApi public val key: String,
private val stateHolder: SaveableStateHolder,
public val disposeBehavior: NavigatorDisposeBehavior,
public val parent: Navigator? = null
Expand Down Expand Up @@ -180,3 +186,9 @@ public data class NavigatorDisposeBehavior(
val disposeNestedNavigators: Boolean = true,
val disposeSteps: Boolean = true,
)

@InternalVoyagerApi
@Composable
public fun compositionUniqueId(): String = currentCompositeKeyHash.toString(MaxSupportedRadix)

private val MaxSupportedRadix = 36
Expand Up @@ -15,6 +15,7 @@ public val LocalNavigatorSaver: ProvidableCompositionLocal<NavigatorSaver<*>> =
public fun interface NavigatorSaver<Saveable : Any> {
public fun saver(
initialScreens: List<Screen>,
key: String,
stateHolder: SaveableStateHolder,
disposeBehavior: NavigatorDisposeBehavior,
parent: Navigator?
Expand All @@ -32,9 +33,9 @@ public fun interface NavigatorSaver<Saveable : Any> {
*
* If you want to use only Parcelable and want a NavigatorSaver that forces the use Parcelable, you can use [parcelableNavigatorSaver].
*/
public fun defaultNavigatorSaver(): NavigatorSaver<Any> = NavigatorSaver { _, stateHolder, disposeBehavior, parent ->
public fun defaultNavigatorSaver(): NavigatorSaver<Any> = NavigatorSaver { _, key, stateHolder, disposeBehavior, parent ->
listSaver(
save = { navigator -> navigator.items },
restore = { items -> Navigator(items, stateHolder, disposeBehavior, parent) }
restore = { items -> Navigator(items, key, stateHolder, disposeBehavior, parent) }
)
}
Expand Up @@ -17,16 +17,17 @@ internal val LocalNavigatorStateHolder: ProvidableCompositionLocal<SaveableState
@Composable
internal fun rememberNavigator(
screens: List<Screen>,
key: String,
disposeBehavior: NavigatorDisposeBehavior,
parent: Navigator?,
): Navigator {
val stateHolder = LocalNavigatorStateHolder.current
val navigatorSaver = LocalNavigatorSaver.current
val saver = remember(navigatorSaver, stateHolder, parent, disposeBehavior) {
navigatorSaver.saver(screens, stateHolder, disposeBehavior, parent)
navigatorSaver.saver(screens, key, stateHolder, disposeBehavior, parent)
}

return rememberSaveable(saver = saver) {
Navigator(screens, stateHolder, disposeBehavior, parent)
return rememberSaveable(saver = saver, key = key) {
Navigator(screens, key, stateHolder, disposeBehavior, parent)
}
}

0 comments on commit df87d6e

Please sign in to comment.