Coverage Summary for Class: BottomSheetSceneStrategy (com.georgeci.moneysurfer.navigation)
| Class |
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| BottomSheetSceneStrategy |
0%
(0/2)
|
0%
(0/6)
|
0%
(0/11)
|
0%
(0/43)
|
| BottomSheetSceneStrategy$Companion |
0%
(0/2)
|
|
0%
(0/2)
|
0%
(0/12)
|
| Total |
0%
(0/4)
|
0%
(0/6)
|
0%
(0/13)
|
0%
(0/55)
|
package com.georgeci.moneysurfer.navigation
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.ModalBottomSheetProperties
import androidx.compose.runtime.Composable
import androidx.navigation3.runtime.NavEntry
import androidx.navigation3.scene.OverlayScene
import androidx.navigation3.scene.Scene
import androidx.navigation3.scene.SceneStrategy
import androidx.navigation3.scene.SceneStrategyScope
/** An [OverlayScene] that renders an [entry] within a [ModalBottomSheet]. */
@OptIn(ExperimentalMaterial3Api::class)
internal class BottomSheetScene<T : Any>(
override val key: Any,
private val entry: NavEntry<T>,
override val previousEntries: List<NavEntry<T>>,
override val overlaidEntries: List<NavEntry<T>>,
private val modalBottomSheetProperties: ModalBottomSheetProperties,
private val onBack: () -> Unit,
) : OverlayScene<T> {
override val entries: List<NavEntry<T>> = listOf(entry)
override val content: @Composable () -> Unit = {
ModalBottomSheet(
onDismissRequest = onBack,
properties = modalBottomSheetProperties,
) {
entry.Content()
}
}
}
/**
* A [SceneStrategy] that displays entries marked with [bottomSheet] metadata inside a
* [ModalBottomSheet], keeping the previous entry composed underneath.
*
* Based on the Navigation 3 bottom sheet recipe:
* https://developer.android.com/guide/navigation/navigation-3/recipes/bottomsheet
*
* Chain before any non-overlay strategies.
*/
@OptIn(ExperimentalMaterial3Api::class)
class BottomSheetSceneStrategy<T : Any> : SceneStrategy<T> {
override fun SceneStrategyScope<T>.calculateScene(entries: List<NavEntry<T>>): Scene<T>? {
val lastEntry = entries.lastOrNull() ?: return null
val properties = lastEntry.metadata[BOTTOM_SHEET_KEY] as? ModalBottomSheetProperties
?: return null
return BottomSheetScene(
key = lastEntry.contentKey,
entry = lastEntry,
previousEntries = entries.dropLast(1),
overlaidEntries = entries.dropLast(1),
modalBottomSheetProperties = properties,
onBack = onBack,
)
}
companion object {
/** Mark a [NavEntry] so this strategy renders it inside a [ModalBottomSheet]. */
fun bottomSheet(
modalBottomSheetProperties: ModalBottomSheetProperties = ModalBottomSheetProperties(),
): Map<String, Any> = mapOf(BOTTOM_SHEET_KEY to modalBottomSheetProperties)
internal const val BOTTOM_SHEET_KEY = "bottomSheet"
}
}