Skip to content
Next Next commit
[Owl] Migrates to navigation-compose
  • Loading branch information
JoseAlcerreca committed Oct 30, 2020
commit 474dc79a8a9b586f2324f2a6fe48baade57dc63f
1 change: 1 addition & 0 deletions Owl/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ dependencies {
implementation Libs.Kotlin.stdlib

implementation Libs.AndroidX.coreKtx
implementation Libs.AndroidX.navigation

implementation Libs.AndroidX.Compose.runtime
implementation Libs.AndroidX.Compose.foundation
Expand Down
31 changes: 10 additions & 21 deletions Owl/app/src/main/java/com/example/owl/ui/NavGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,26 @@

package com.example.owl.ui

import android.os.Parcelable
import androidx.compose.runtime.Immutable
import com.example.owl.ui.utils.Navigator
import kotlinx.android.parcel.Parcelize
import androidx.navigation.NavHostController
import androidx.navigation.compose.navigate

/**
* Models the screens in the app and any arguments they require.
*/
sealed class Destination : Parcelable {
@Parcelize
object Onboarding : Destination()

@Parcelize
object Courses : Destination()

@Immutable
@Parcelize
data class Course(val courseId: Long) : Destination()
object Destinations {
const val Onboarding = "Onboarding_dest_key"
const val Courses = "Courses_dest_key"
const val CourseDetails = "Courses_dest_key"
}

/**
* Models the navigation actions in the app.
*/
class Actions(navigator: Navigator<Destination>) {
class Actions(navController: NavHostController) {
val onboardingComplete: () -> Unit = {
navigator.navigate(Destination.Courses)
navController.navigate(Destinations.Courses)
}
val selectCourse: (Long) -> Unit = { courseId: Long ->
navigator.navigate(Destination.Course(courseId))
navController.navigate(Destinations.CourseDetails + "/$courseId")
}
val upPress: () -> Unit = {
navigator.back()
navController.popBackStack()
}
}
34 changes: 18 additions & 16 deletions Owl/app/src/main/java/com/example/owl/ui/OwlApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,40 @@
package com.example.owl.ui

import androidx.activity.OnBackPressedDispatcher
import androidx.compose.animation.Crossfade
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Providers
import androidx.compose.runtime.remember
import androidx.compose.runtime.savedinstancestate.rememberSavedInstanceState
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.example.owl.ui.course.CourseDetails
import com.example.owl.ui.courses.Courses
import com.example.owl.ui.onboarding.Onboarding
import com.example.owl.ui.utils.AmbientBackDispatcher
import com.example.owl.ui.utils.Navigator
import com.example.owl.ui.utils.ProvideDisplayInsets
import com.example.owl.ui.utils.ProvideImageLoader

@Composable
fun OwlApp(backDispatcher: OnBackPressedDispatcher) {
@Suppress("RemoveExplicitTypeArguments")
val navigator: Navigator<Destination> = rememberSavedInstanceState(
saver = Navigator.saver<Destination>(backDispatcher)
) {
Navigator(Destination.Onboarding, backDispatcher)
}
val actions = remember(navigator) { Actions(navigator) }

Providers(AmbientBackDispatcher provides backDispatcher) {
ProvideDisplayInsets {
ProvideImageLoader {
Crossfade(navigator.current) { destination ->
when (destination) {
Destination.Onboarding -> Onboarding(actions.onboardingComplete)
Destination.Courses -> Courses(actions.selectCourse)
is Destination.Course -> CourseDetails(
destination.courseId,
val navController = rememberNavController()

val actions = remember(navController) { Actions(navController) }
NavHost(navController = navController, startDestination = Destinations.Onboarding) {
composable(Destinations.Onboarding) {
Onboarding(actions.onboardingComplete)
}
composable(Destinations.Courses) {
Courses(actions.selectCourse)
}
composable(Destinations.CourseDetails + "/{courseId}") { backStackEntry ->
val courseId = backStackEntry.arguments?.getLong("courseId")
?: throw IllegalArgumentException("No course ID provided")
CourseDetails(
courseId,
actions.selectCourse,
actions.upPress
)
Expand Down
49 changes: 0 additions & 49 deletions Owl/app/src/main/java/com/example/owl/ui/utils/Navigation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,61 +16,12 @@

package com.example.owl.ui.utils

import android.os.Parcelable
import androidx.activity.OnBackPressedCallback
import androidx.activity.OnBackPressedDispatcher
import androidx.compose.runtime.Composable
import androidx.compose.runtime.onCommit
import androidx.compose.runtime.remember
import androidx.compose.runtime.savedinstancestate.listSaver
import androidx.compose.runtime.staticAmbientOf
import androidx.compose.runtime.toMutableStateList

/**
* A simple navigator which maintains a back stack.
*/
class Navigator<T : Parcelable> private constructor(
initialBackStack: List<T>,
backDispatcher: OnBackPressedDispatcher
) {
constructor(
initial: T,
backDispatcher: OnBackPressedDispatcher
) : this(listOf(initial), backDispatcher)

private val backStack = initialBackStack.toMutableStateList()
private val backCallback = object : OnBackPressedCallback(canGoBack()) {
override fun handleOnBackPressed() {
back()
}
}.also { callback ->
backDispatcher.addCallback(callback)
}
val current: T get() = backStack.last()

fun back() {
backStack.removeAt(backStack.lastIndex)
backCallback.isEnabled = canGoBack()
}

fun navigate(destination: T) {
backStack += destination
backCallback.isEnabled = canGoBack()
}

private fun canGoBack(): Boolean = backStack.size > 1

companion object {
/**
* Serialize the back stack to save to instance state.
*/
fun <T : Parcelable> saver(backDispatcher: OnBackPressedDispatcher) =
listSaver<Navigator<T>, T>(
save = { navigator -> navigator.backStack.toList() },
restore = { backstack -> Navigator(backstack, backDispatcher) }
)
}
}

/**
* An effect for handling presses of the device back button.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ object Libs {

object AndroidX {
const val coreKtx = "androidx.core:core-ktx:1.5.0-alpha04"
const val navigation = "androidx.navigation:navigation-compose:1.0.0-alpha01"

object Compose {
const val snapshot = ""
Expand Down