Skip to content

Commit

Permalink
Added keySaver property to ComposeNavigator
Browse files Browse the repository at this point in the history
  • Loading branch information
chRyNaN committed Feb 27, 2022
1 parent 0237e67 commit 23bdc22
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ package com.chrynan.navigation.compose

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.saveable.autoSaver
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable

@Composable
@ExperimentalNavigationApi
internal actual fun <Context, Key> InternalNavContainer(
navigator: BaseComposeNavigatorByContentViewModel<Context, Key>
) {
val contentKey by navigator.keyChanges.collectAsState(initial = navigator.initialKey)
val contentKey = rememberSaveable(navigator.keySaver) { mutableStateOf(navigator.initialKey) }

navigator.keyChanges.collectAsStateIn(state = contentKey)

val scope = object : ComposeNavigationContentScope<Key> {

Expand All @@ -21,7 +21,7 @@ internal actual fun <Context, Key> InternalNavContainer(

Box {
navigator.apply {
scope.content(contentKey)
scope.content(contentKey.value)
}
}

Expand All @@ -34,11 +34,13 @@ internal actual fun <Context, Key, NavigationScope : ComposeNavigationKeyScope<K
navigator: BaseComposeNavigatorByKeyViewModel<Context, Key, NavigationScope>,
scope: NavigationScope
) {
val contentKey by navigator.keyChanges.collectAsState(initial = navigator.initialKey)
val contentKey = rememberSaveable(navigator.keySaver) { mutableStateOf(navigator.initialKey) }

navigator.keyChanges.collectAsStateIn(state = contentKey)

Box {
navigator.apply {
scope.content(contentKey)
scope.content(contentKey.value)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ interface ComposeNavigationIntentStackNavigatorByKey<I : NavigationIntent> :
class ComposeNavigationIntentNavigatorByKeyViewModel<Context, Intent : NavigationIntent> internal constructor(
initialScope: Context,
initialKeys: (Context) -> Intent,
keySaver: Saver<Intent, Any>,
override val content: @Composable ComposeNavigationIntentScope<Intent>.(key: Intent) -> Unit
) : BaseComposeNavigatorByKeyViewModel<Context, Intent, ComposeNavigationIntentScope<Intent>>(
initialContext = initialScope,
initialKeys = initialKeys
initialKeys = initialKeys,
keySaver = keySaver
), ComposeNavigationIntentStackNavigatorByKey<Intent>
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,29 @@ import com.chrynan.navigation.NavStackDuplicateContentStrategy
import com.chrynan.navigation.Navigator

@ExperimentalNavigationApi
interface ComposeNavigator<T> : Navigator {
interface ComposeNavigator<Key> : Navigator {

val initialKey: T
val initialKey: Key

val currentKey: T
val currentKey: Key

val keyChanges: Flow<T>
val keyChanges: Flow<Key>

val isInitialized: Boolean

val keySaver: Saver<Key, Any>

companion object
}

@ExperimentalNavigationApi
interface ComposeNavigatorByContent<T> : ComposeNavigator<T> {
interface ComposeNavigatorByContent<Key> : ComposeNavigator<Key> {

@Composable
fun goTo(
key: T,
key: Key,
strategy: NavStackDuplicateContentStrategy,
content: @Composable ComposeNavigationContentScope<T>.() -> Unit
content: @Composable ComposeNavigationContentScope<Key>.() -> Unit
)

companion object
Expand All @@ -38,14 +40,14 @@ interface ComposeNavigatorByContent<T> : ComposeNavigator<T> {
@Suppress("unused")
@ExperimentalNavigationApi
@Composable
fun <T> ComposeNavigatorByContent<T>.goTo(key: T, content: @Composable ComposeNavigationContentScope<T>.() -> Unit) =
fun <Key> ComposeNavigatorByContent<Key>.goTo(key: Key, content: @Composable ComposeNavigationContentScope<Key>.() -> Unit) =
goTo(key = key, strategy = NavStackDuplicateContentStrategy.CLEAR_STACK, content = content)

@ExperimentalNavigationApi
interface ComposeNavigatorByKey<T> : ComposeNavigator<T> {
interface ComposeNavigatorByKey<Key> : ComposeNavigator<Key> {

fun goTo(
key: T,
key: Key,
strategy: NavStackDuplicateContentStrategy
)

Expand All @@ -55,11 +57,11 @@ interface ComposeNavigatorByKey<T> : ComposeNavigator<T> {
// Note: This is needed because defaults aren't working for @Composable functions for interfaces.
@Suppress("unused")
@ExperimentalNavigationApi
fun <T> ComposeNavigatorByKey<T>.goTo(key: T) =
fun <Key> ComposeNavigatorByKey<Key>.goTo(key: Key) =
goTo(key = key, strategy = NavStackDuplicateContentStrategy.CLEAR_STACK)

@ExperimentalNavigationApi
interface ComposeStackNavigator<T> : ComposeNavigator<T> {
interface ComposeStackNavigator<Key> : ComposeNavigator<Key> {

fun canGoBack(): Boolean

Expand All @@ -69,15 +71,15 @@ interface ComposeStackNavigator<T> : ComposeNavigator<T> {
}

@ExperimentalNavigationApi
interface ComposeStackNavigatorByContent<T> : ComposeStackNavigator<T>,
ComposeNavigatorByContent<T> {
interface ComposeStackNavigatorByContent<Key> : ComposeStackNavigator<Key>,
ComposeNavigatorByContent<Key> {

companion object
}

@ExperimentalNavigationApi
interface ComposeStackNavigatorByKey<T> : ComposeStackNavigator<T>,
ComposeNavigatorByKey<T> {
interface ComposeStackNavigatorByKey<Key> : ComposeStackNavigator<Key>,
ComposeNavigatorByKey<Key> {

companion object
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ abstract class BaseComposeNavigatorByContentViewModel<Context, Key> : ViewModel(
@ExperimentalNavigationApi
class ComposeNavigatorByContentViewModel<Context, Key> internal constructor(
override val initialContext: Context,
override val keySaver: Saver<Key, Any>,
private val initialKeysAndContent: (Context) -> Pair<Key, @Composable ComposeNavigationContentScope<Key>.() -> Unit>
) : BaseComposeNavigatorByContentViewModel<Context, Key>() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.filterNotNull
@ExperimentalNavigationApi
abstract class BaseComposeNavigatorByKeyViewModel<Context, Key, NavigationScope : ComposeNavigationKeyScope<Key>>(
final override val initialContext: Context,
final override val keySaver: Saver<Key, Any>,
private val initialKeys: (Context) -> Key
) : ViewModel(),
ComposeNavigator<Key>,
Expand Down Expand Up @@ -110,10 +111,12 @@ abstract class BaseComposeNavigatorByKeyViewModel<Context, Key, NavigationScope

@ExperimentalNavigationApi
class ComposeNavigatorByKeyViewModel<Context, Key> internal constructor(
initialScope: Context,
initialContext: Context,
initialKeys: (Context) -> Key,
keySaver: Saver<Key, Any>,
override val content: @Composable ComposeNavigationKeyScope<Key>.(key: Key) -> Unit
) : BaseComposeNavigatorByKeyViewModel<Context, Key, ComposeNavigationKeyScope<Key>>(
initialContext = initialScope,
initialKeys = initialKeys
initialContext = initialContext,
initialKeys = initialKeys,
keySaver = keySaver
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
@file:Suppress("unused")

package com.chrynan.navigation.compose

import androidx.compose.runtime.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.experimental.ExperimentalTypeInference

/**
* Similar to the [collectAsState] function but allows providing the [MutableState] to be used.
*
* @see [collectAsState]
*/
@Composable
internal fun <T : R, R> Flow<T>.collectAsStateIn(
state: MutableState<R>,
context: CoroutineContext = EmptyCoroutineContext
): State<R> = produceStateIn(state = state, this, context) {
if (context == EmptyCoroutineContext) {
collect { value = it }
} else withContext(context) {