Created this navigation library for Compose/WASM, ...
# feed
t
Created this navigation library for Compose/WASM, which lets you do SPA (Single Page Application)- style navigation with a full Compose UI. This will give a more native web feel to your Compose Website. And the best part, you don't even need to run a server for it. You can configure your CDN or any static server to serve your website. GitHub: github.com/Taz03/compose-web-navigator
馃憤 1
u
what is the difference compared to github.com/terrakok/navigation3-browser
t
1. Ability to do native path navigation without the # trick, which is used to navigate between a single page 2. Path parameters, like
/user/:id
So a navigation3-browser url will look like
<http://example.com/#user/?id=taz|example.com/#user/?id=taz>
But with compose-web-navigator it'll look like the usual
<http://example.com/user/taz|example.com/user/taz>
My library has built-in features for Tab titles and 404 pages, which you can implement in your custom logic in the navigation3-browser library as well. But it'd be easier to do with this library. Also this library is very lightweight.
u
馃挴
j
@Tanish Azad to be fair you can do full urls with paths and such without the hashtag with navigation3 (I did it), however I felt it wasn't straight forward and I had to do a bunch of custom logic 馃檪
t
Ohh, thanks for letting me know, I was unaware of that. Can you share how to do that?
j
step 1 would be to have the server feed your app from any url you are calling (I guess that is common). For web pack you need to set
config.devServer.historyApiFallback = true;
and then I think it works. then afterwards you would have to get the current path and then parse it into your destination, which is the annoying part with nested navigation, if you have nested NavDisplays. After this, I made my own helper method to create the url from back stack entries and I was overriding the contentKey:
Copy code
NavDisplay(
  backStack = someBackStack,
  entryDecorators = listOf(rememberViewModelStoreNavEntryDecorator()),
) { entry -> 
   // I like this way to define Nav entries so we can pattern match with when(..)
   when (entry) {
     is SomeState.Home -> NavEntry(entry, "home") { // <-- we pass "home" as contentKey
        HomeScreen()
     }
     is SomeState.About -> NavEntry(entry, "about") { // <-- we pass "about" as contentKey
        AboutScreen()
     }
   }
}
Now we successfully set the content key to our nav entry. Now we just have to put that stuff back into the url using HierarchicalBrowserNavigation from terrakok Here I do have to say that I have nested nav displays, so it should go through the stack and then build up the url from the nested graph. So lets say I have a home screen, with a bottom navigation and 3 different pages, home/overview, home/settings, home/about or whatever, it should recursively find these. By relying on the contentKey we can customly name destinations. So you can also set a content key like:
NavEntry(entry, "details/${entry.id}")
Copy code
@Composable
fun SetupBrowserHistory() {
    val dispatcher = LocalNavigationEventDispatcherOwner.current?.navigationEventDispatcher ?: return
    val history by dispatcher.history.collectAsState()

    HierarchicalBrowserNavigation(
        currentDestinationName = {
            val fullHistory = history.mergedHistory.flatMap { info ->
                buildList {
                    if (info is SceneInfo<*>) {
                        info.scene.entries.lastOrNull()?.contentKey?.toString()?.let(::add)
                            ?: add(info.scene.key.toString())
                    } else {
                        info::class.simpleName
                    }
                }
            }
            fullHistory
                .filterIndexed { index, contentKey ->
                    fullHistory.getOrNull(index + 1)?.startsWith("$contentKey/", false) != true
                }
                .joinToString("/")
        },
    )
}
As said, the shitty part is to parse the original url into a nested graph. For that I can't share the code because it is very specific. Something with getting the path and then passing it down until there are no more consumers.
馃憤 1