Skip to content

Commit

Permalink
Created NavigationContext interface
Browse files Browse the repository at this point in the history
  • Loading branch information
chRyNaN committed Feb 26, 2022
1 parent 91fb6ae commit 80d29ab
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package com.chrynan.navigation.compose

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.chrynan.navigation.NavigationContext
import com.chrynan.navigation.NavigationIntent
import com.chrynan.navigation.Navigator

Expand Down Expand Up @@ -57,9 +58,9 @@ fun <Key> rememberNavigatorByContent(
* Example usage:
* ```kotlin
* val navigator = rememberNavigatorByContent(
* initialScope = BottomNavBarItem.HOME,
* initialKeysAndContent = { scope ->
* when (scope) {
* initialContext = BottomNavBarItem.HOME,
* initialContent = { context ->
* when (context) {
* is BottomNavBarItem.HOME -> "Greeting" to { Text("Hello") }
* }
* }
Expand Down Expand Up @@ -95,6 +96,53 @@ fun <Context, Key> rememberNavigatorByContent(
)
}

/**
* Creates and remembers a [ComposeNavigator] that can navigate with a key and [Composable] content. This allows for
* explicitly specifying the [Composable] content to navigate to at the [ComposeNavigatorByContent.goTo] function call
* site. Meaning the [Composable] content is more flexible and doesn't need to specified upfront when creating this
* [ComposeNavigatorByContent].
*
* Example usage:
* ```kotlin
* val navigator = rememberNavigatorByContent(
* initialContext = BottomNavBarItem.HOME,
* initialContent = { context ->
* when (context) {
* is BottomNavBarItem.HOME -> "Greeting" to { Text("Hello") }
* }
* }
* )
*
* // The NavContainer will start by displaying the initial content, which in this case is "Hello".
* NavContainer(navigator)
*
* // The above NavContainer will display "Good-bye" after the following call:
* navigator.goTo("Farewell") { Text("Good-bye") }
*
* // Goes back to the initial content: "Hello":
* navigator.goBack()
* ```
*
* **Note:** That it is typical to use a [ComposeNavigator] with a [NavContainer] to display the [Composable] content
* and listen to changes.
*
* **Note:** That this function differs slightly from the [rememberNavigatorByContent] function in that this function
* allows changing of scopes, which is useful for more complex navigation.
*
* @see [rememberNavigatorByContent]
*/
@ExperimentalNavigationApi
@Composable
fun <Context : NavigationContext<Key>, Key> rememberNavigatorByContent(
initialContext: Context,
initialContent: (Context) -> @Composable ComposeNavigationContentScope<Key>.() -> Unit
): ComposeNavigatorByContentViewModel<Context, Key> = remember {
ComposeNavigatorByContentViewModel(
initialContext = initialContext,
initialKeysAndContent = { it.initialKey to initialContent(it) }
)
}

/**
* Creates and remembers a [ComposeNavigator] that can navigate with a key. This allows for specifying the [Composable]
* content up front when creating this [ComposeNavigatorByKey] and simply navigating with a key from the
Expand Down Expand Up @@ -149,7 +197,7 @@ fun <Key> rememberNavigatorByKey(
* Example usage:
* ```kotlin
* val navigator = rememberNavigatorByKey(
* initialScope = BottomNavBarItem.HELLO,
* initialContext = BottomNavBarItem.HELLO,
* initialKeys = { scope ->
* when(scope) {
* BottomNavBarItem.HELLO -> "Greeting"
Expand All @@ -176,7 +224,7 @@ fun <Key> rememberNavigatorByKey(
* navigator.goBack()
*
* // Changes the scope to BottomNavBarItem.GOODBYE and displays its initial key, which in this case is "Farewell"
* navigator.changeScope(BottomNavBarItem.GOODBYE)
* navigator.changeContext(BottomNavBarItem.GOODBYE)
* ```
*
* **Note:** That it is typical to use a [ComposeNavigator] with a [NavContainer] to display the [Composable] content
Expand All @@ -201,6 +249,58 @@ fun <Context, Key> rememberNavigatorByKey(
)
}

/**
* Creates and remembers a [ComposeNavigator] that can navigate with a key. This allows for specifying the [Composable]
* content up front when creating this [ComposeNavigatorByKey] and simply navigating with a key from the
* [ComposeNavigatorByKey.goTo] function.
*
* Example usage:
* ```kotlin
* val navigator = rememberNavigatorByKey(
* initialContext = BottomNavBarItem.HELLO,
* content = { key ->
* when(key) {
* "Greeting" -> Text("Hello")
* "Farewell" -> Text("Good-bye")
* else -> Text("Unexpected Key: $key")
* }
* }
* )
*
* // The NavContainer will start by displaying the initial content, which in this case is "Hello"
* NavContainer(navigator)
*
* // The above NavContainer will display "Good Bye" after the following call:
* navigator.goTo("Farewell")
*
* // Goes back to the initial content: "Hello":
* navigator.goBack()
*
* // Changes the scope to BottomNavBarItem.GOODBYE and displays its initial key, which in this case is "Farewell"
* navigator.changeContext(BottomNavBarItem.GOODBYE)
* ```
*
* **Note:** That it is typical to use a [ComposeNavigator] with a [NavContainer] to display the [Composable] content
* and listen to changes.
*
* **Note:** That this function differs slightly from the [rememberNavigatorByKey] function in that this function allows
* changing of scopes, which is useful for more complex navigation.
*
* @see [rememberNavigatorByKey]
*/
@ExperimentalNavigationApi
@Composable
fun <Context : NavigationContext<Key>, Key> rememberNavigatorByKey(
initialContext: Context,
content: @Composable ComposeNavigationKeyScope<Key>.(key: Key) -> Unit
): ComposeNavigatorByKeyViewModel<Context, Key> = remember {
ComposeNavigatorByKeyViewModel(
initialScope = initialContext,
initialKeys = { it.initialKey },
content = content
)
}

/**
* Creates and remembers a [ComposeNavigator] that can navigate with a [NavigationIntent] as a key. This allows for
* specifying the [Composable] content up front when creating this [ComposeNavigatorByKey] and simply navigating with
Expand Down Expand Up @@ -257,7 +357,7 @@ fun <Intent : NavigationIntent> rememberNavigatorByIntent(
* Example usage:
* ```kotlin
* val navigator = rememberNavigatorByKey(
* initialScope = BottomNavBarItem.HELLO,
* initialContext = BottomNavBarItem.HELLO,
* initialKeys = { scope ->
* when(scope) {
* BottomNavBarItem.HELLO -> HomeNavigationIntent.Greeting
Expand Down Expand Up @@ -304,3 +404,52 @@ fun <Context, Intent : NavigationIntent> rememberNavigatorByIntent(
content = content
)
}

/**
* Creates and remembers a [ComposeNavigator] that can navigate with a [NavigationIntent] as a key. This allows for
* specifying the [Composable] content up front when creating this [ComposeNavigatorByKey] and simply navigating with
* a [NavigationIntent] key from the [ComposeNavigatorByKey.goTo] function. The returned [ComposeNavigator] implements
* the [Navigator] interface.
*
* Example usage:
* ```kotlin
* val navigator = rememberNavigatorByKey(
* initialContext = BottomNavBarItem.HELLO,
* content = { navigationIntent ->
* when(navigationIntent) {
* HomeNavigationIntent.Greeting -> Text("Hello")
* HomeNavigationIntent.Farewell -> Text("Good-bye")
* }
* }
* )
*
* // The NavContainer will start by displaying the initial content, which in this case is "Hello"
* NavContainer(navigator)
*
* // The above NavContainer will display "Good Bye" after the following call:
* navigator.goTo(HomeNavigationIntent.Farewell)
*
* // Goes back to the initial content: "Hello":
* navigator.goBack()
* ```
*
* **Note:** That it is typical to use a [ComposeNavigator] with a [NavContainer] to display the [Composable] content
* and listen to changes.
*
* **Note:** That this function differs slightly from the [rememberNavigatorByIntent] function in that this function
* allows changing of scopes, which is useful for more complex navigation.
*
* @see [rememberNavigatorByIntent]
*/
@ExperimentalNavigationApi
@Composable
fun <Context : NavigationContext<Intent>, Intent : NavigationIntent> rememberNavigatorByIntent(
initialContext: Context,
content: @Composable ComposeNavigationIntentScope<Intent>.(intent: Intent) -> Unit
): ComposeNavigationIntentNavigatorByKeyViewModel<Context, Intent> = remember {
ComposeNavigationIntentNavigatorByKeyViewModel(
initialScope = initialContext,
initialKeys = { it.initialKey },
content = content
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.chrynan.navigation

/**
* Represents a navigation context, or a container of a back stack of [Key]s. Navigation can take place within a
* [NavigationContext] typically by changing [Key] values. But an application may have multiple [NavigationContext]s
* that can be changed and navigated through. This allows for more complex navigation paradigms, such as retaining
* multiple back stacks for a bottom navigation UI component.
*/
interface NavigationContext<Key> {

/**
* The initial key value that should be displayed when first changing to this [NavigationContext] before any other
* navigation was performed.
*/
val initialKey: Key
}

0 comments on commit 80d29ab

Please sign in to comment.