All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.blucky8649.decompose_navhost.navigation.NavController.kt Maven / Gradle / Ivy

Go to download

A Decompose extension library which facilitate writing Jetpack based navigation style code for Compose Multiplatform.

There is a newer version: 1.0.0-alpha04
Show newest version
package com.blucky8649.decompose_navhost.navigation

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.router.stack.ChildStack
import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.router.stack.pop
import com.arkivanov.decompose.router.stack.popWhile
import com.arkivanov.decompose.router.stack.push
import com.arkivanov.decompose.value.Value
import com.arkivanov.essenty.backhandler.BackHandlerOwner

class NavController(
    componentContext: ComponentContext
) : BackHandlerOwner, ComponentContext by componentContext {

    private var _graph: NavGraph? = null
    var graph: NavGraph
        get() {
        return _graph ?: error("Graph is not set")
    } set(value) {
        _graph = value
    }

    private val navigation = StackNavigation()

    val backStack: Value> by lazy {
        childStack(
            source = navigation,
            serializer = null,
            initialConfiguration = NavConfiguration(
                destination = graph.findDestination(graph.startDestination),
            ),
            handleBackButton = true,
            childFactory = { config, _ ->
                NavBackStackEntry(
                    destination = config.destination,
                    navOptions = config.navOptions
                )
            }
        )
    }

    fun popBackStack(onCompleted: (isSuccess: Boolean) -> Unit = {}) {
        val entry = backStack.value.items.lastOrNull()?.instance ?: return

        val inclusive = entry.navOptions.inclusive
        val popUpToRoute = entry.navOptions.popUpToRoute

        if (popUpToRoute.isEmpty()) {
            navigation.pop(onCompleted)
            return
        }

        navigation.popWhile { (topDestinationOfStack, _) ->
            topDestinationOfStack.name != popUpToRoute
        }

        if (inclusive) { navigation.pop(onComplete = onCompleted) }
    }

    fun navigate(
        route: String,
        navOptionsBuilder: NavOptionsBuilder.() -> Unit = {}
    ) {
        val navOptions = NavOptionsBuilder()
            .apply(navOptionsBuilder)
            .build()

        val newConfig = NavConfiguration(
            destination = graph.findDestination(route),
            navOptions = navOptions
        )

        navigation.push(newConfig)
    }
}

data class NavConfiguration(
    val destination: Destination,
    val navOptions: NavOptions = NavOptions()
)

@Composable
fun rememberNavController(
    componentContext: ComponentContext
) = remember { NavController(componentContext) }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy