Skip to content

Commit

Permalink
feat: allow TabNavigator control nested navigators disposal
Browse files Browse the repository at this point in the history
  • Loading branch information
adrielcafe committed Apr 30, 2022
1 parent 437a650 commit c4ec4fb
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 21 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ kotlin.mpp.enableGranularSourceSetsMetadata=true

# Maven
GROUP=cafe.adriel.voyager
VERSION_NAME=1.0.0-rc01
VERSION_NAME=1.0.0-rc02

POM_DESCRIPTION=A pragmatic navigation library for Jetpack Compose
POM_INCEPTION_YEAR=2021
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.lifecycle.LifecycleEffect
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.NavigatorDisposeBehavior
import cafe.adriel.voyager.navigator.tab.LocalTabNavigator
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.sample.androidViewModel.AndroidListViewModel
Expand All @@ -34,10 +33,7 @@ fun Tab.TabContent() {
onDisposed = { Log.d("Navigator", "Dispose tab $tabTitle") },
)

Navigator(
screen = BasicNavigationScreen(index = 0),
disposeBehavior = NavigatorDisposeBehavior(autoDisposeNavigator = false),
) { navigator ->
Navigator(BasicNavigationScreen(index = 0)) { navigator ->
SlideTransition(navigator) { screen ->
val screenModel = rememberScreenModel { ListScreenModel() }
val viewModel = getViewModel<AndroidListViewModel>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,19 @@ public fun Navigator(
CompositionLocalProvider(
LocalNavigatorStateHolder providesDefault rememberSaveableStateHolder()
) {
val navigator = rememberNavigator(screens, LocalNavigator.current)
val navigator = rememberNavigator(screens, disposeBehavior, LocalNavigator.current)
val lifecycleOwner = rememberScreenLifecycleOwner(navigator.lastItem)
val hooks = lifecycleOwner.getHooks()

if (disposeBehavior.autoDisposeNavigator) {
if (navigator.parent?.disposeBehavior?.disposeNestedNavigators != false) {
NavigatorDisposableEffect(navigator)
}

CompositionLocalProvider(
LocalNavigator provides navigator,
*hooks.providers.toTypedArray()
) {
if (disposeBehavior.autoDisposeSteps) {
if (disposeBehavior.disposeSteps) {
StepDisposableEffect(navigator)
}

Expand All @@ -91,6 +91,7 @@ public fun Navigator(

public class Navigator internal constructor(
screens: List<Screen>,
public val disposeBehavior: NavigatorDisposeBehavior,
public val stateHolder: SaveableStateHolder,
public val parent: Navigator? = null
) : Stack<Screen> by screens.toMutableStateStack(minSize = 1) {
Expand Down Expand Up @@ -124,6 +125,6 @@ public class Navigator internal constructor(
}

public data class NavigatorDisposeBehavior(
val autoDisposeNavigator: Boolean = true,
val autoDisposeSteps: Boolean = true,
val disposeNestedNavigators: Boolean = true,
val disposeSteps: Boolean = true,
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import cafe.adriel.voyager.core.lifecycle.ScreenLifecycleStore
import cafe.adriel.voyager.core.model.ScreenModelStore
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.core.stack.StackEvent
import cafe.adriel.voyager.navigator.Navigator

Expand All @@ -17,9 +18,7 @@ internal fun NavigatorDisposableEffect(
DisposableEffect(navigator) {
onDispose {
for (screen in navigator.items) {
ScreenModelStore.remove(screen)
ScreenLifecycleStore.remove(screen)
navigator.stateHolder.removeState(screen.key)
navigator.dispose(screen)
}
navigator.clearEvent()
}
Expand All @@ -35,11 +34,17 @@ internal fun StepDisposableEffect(
DisposableEffect(currentScreen.key) {
onDispose {
if (navigator.lastEvent in disposableEvents) {
ScreenModelStore.remove(currentScreen)
ScreenLifecycleStore.remove(currentScreen)
navigator.stateHolder.removeState(currentScreen.key)
navigator.dispose(currentScreen)
navigator.clearEvent()
}
}
}
}

private fun Navigator.dispose(
screen: Screen
) {
ScreenModelStore.remove(screen)
ScreenLifecycleStore.remove(screen)
stateHolder.removeState(screen.key)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,30 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.staticCompositionLocalOf
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.NavigatorDisposeBehavior

internal val LocalNavigatorStateHolder: ProvidableCompositionLocal<SaveableStateHolder> =
staticCompositionLocalOf { error("LocalNavigatorStateHolder not initialized") }

@Composable
internal fun rememberNavigator(
screens: List<Screen>,
disposeBehavior: NavigatorDisposeBehavior,
parent: Navigator?
): Navigator {
val stateHolder = LocalNavigatorStateHolder.current

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

private fun navigatorSaver(
stateHolder: SaveableStateHolder,
disposeBehavior: NavigatorDisposeBehavior,
parent: Navigator?
): Saver<Navigator, Any> =
listSaver(
save = { navigator -> navigator.items },
restore = { items -> Navigator(items, stateHolder, parent) }
restore = { items -> Navigator(items, disposeBehavior, stateHolder, parent) }
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ public val LocalTabNavigator: ProvidableCompositionLocal<TabNavigator> =
@Composable
public fun TabNavigator(
tab: Tab,
disposeNestedNavigators: Boolean = false,
content: TabNavigatorContent = { CurrentTab() }
) {
Navigator(
screen = tab,
disposeBehavior = NavigatorDisposeBehavior(autoDisposeSteps = false),
disposeBehavior = NavigatorDisposeBehavior(
disposeNestedNavigators = disposeNestedNavigators,
disposeSteps = false
),
onBackPressed = null
) { navigator ->
val tabNavigator = remember(navigator) {
Expand Down

0 comments on commit c4ec4fb

Please sign in to comment.