Skip to content

Instantly share code, notes, and snippets.

@zsoltk
Created December 22, 2019 13:03
Show Gist options
  • Save zsoltk/c266984d3f0e560847cc0cb381cd0638 to your computer and use it in GitHub Desktop.
Save zsoltk/c266984d3f0e560847cc0cb381cd0638 to your computer and use it in GitHub Desktop.
@Composable
// id is a new parameter we'll use for the key in the map:
fun <T> BackHandler(id: Any, routing: T, children: @Composable() (BackStack<T>) -> Unit) {
// grab the parent handler, wherever it's up the tree
val upstream = +ambient(backPressHandler)
// is there a back stack in the upstream? then let's grab the map of the last entry
val saveRestorePoint = upstream.backStack?.lastEntry()?.children
// use existing or fall back to new instance
val backStack = saveRestorePoint?.get(id) ?: BackStack(routing).also {
saveRestorePoint?.set(id, it)
}
// to keep track of children down the tree
val downstream = +memo { ScopedBackPressHandler(backStack) }
// ...
// from here on it's the same as before + a cast in the last line
// ...
// our lambda for handling back press: asking all children,
val handleBackPressHere: () -> Boolean = { downstream.handle() || backStack.pop() }
// register our handler in the parent handler
upstream.handlers.add(handleBackPressHere)
// remove ourselves from the parent handler when this level goes away
+onDispose { upstream.handlers.remove(handleBackPressHere) }
// override the ambient so that it points to this level
// so that we'll become the upstream of some child later:
backPressHandler.Provider(value = downstream) {
// add client code Composable, which will have access to back stack
// we need an ugly cast to make it work though
children(backStack as BackStack<T>)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment