AdaptiveSheet.kt 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package eu.kanade.presentation.components
  2. import androidx.activity.compose.BackHandler
  3. import androidx.compose.animation.core.tween
  4. import androidx.compose.animation.fadeIn
  5. import androidx.compose.animation.fadeOut
  6. import androidx.compose.animation.with
  7. import androidx.compose.foundation.layout.PaddingValues
  8. import androidx.compose.foundation.layout.WindowInsets
  9. import androidx.compose.foundation.layout.WindowInsetsSides
  10. import androidx.compose.foundation.layout.asPaddingValues
  11. import androidx.compose.foundation.layout.navigationBars
  12. import androidx.compose.foundation.layout.only
  13. import androidx.compose.runtime.Composable
  14. import androidx.compose.ui.unit.Dp
  15. import androidx.compose.ui.unit.dp
  16. import cafe.adriel.voyager.core.lifecycle.DisposableEffectIgnoringConfiguration
  17. import cafe.adriel.voyager.core.screen.Screen
  18. import cafe.adriel.voyager.navigator.Navigator
  19. import cafe.adriel.voyager.transitions.ScreenTransition
  20. import eu.kanade.presentation.util.isTabletUi
  21. import tachiyomi.presentation.core.components.AdaptiveSheet as AdaptiveSheetImpl
  22. @Composable
  23. fun NavigatorAdaptiveSheet(
  24. screen: Screen,
  25. tonalElevation: Dp = 1.dp,
  26. enableSwipeDismiss: (Navigator) -> Boolean = { true },
  27. onDismissRequest: () -> Unit,
  28. ) {
  29. Navigator(
  30. screen = screen,
  31. content = { sheetNavigator ->
  32. AdaptiveSheet(
  33. tonalElevation = tonalElevation,
  34. enableSwipeDismiss = enableSwipeDismiss(sheetNavigator),
  35. onDismissRequest = onDismissRequest,
  36. ) {
  37. ScreenTransition(
  38. navigator = sheetNavigator,
  39. transition = {
  40. fadeIn(animationSpec = tween(220, delayMillis = 90)) with
  41. fadeOut(animationSpec = tween(90))
  42. },
  43. )
  44. BackHandler(
  45. enabled = sheetNavigator.size > 1,
  46. onBack = sheetNavigator::pop,
  47. )
  48. }
  49. // Make sure screens are disposed no matter what
  50. if (sheetNavigator.parent?.disposeBehavior?.disposeNestedNavigators == false) {
  51. DisposableEffectIgnoringConfiguration {
  52. onDispose {
  53. sheetNavigator.items
  54. .asReversed()
  55. .forEach(sheetNavigator::dispose)
  56. }
  57. }
  58. }
  59. },
  60. )
  61. }
  62. /**
  63. * Sheet with adaptive position aligned to bottom on small screen, otherwise aligned to center
  64. * and will not be able to dismissed with swipe gesture.
  65. *
  66. * Max width of the content is set to 460 dp.
  67. */
  68. @Composable
  69. fun AdaptiveSheet(
  70. tonalElevation: Dp = 1.dp,
  71. enableSwipeDismiss: Boolean = true,
  72. onDismissRequest: () -> Unit,
  73. content: @Composable (PaddingValues) -> Unit,
  74. ) {
  75. val isTabletUi = isTabletUi()
  76. AdaptiveSheetImpl(
  77. isTabletUi = isTabletUi,
  78. tonalElevation = tonalElevation,
  79. enableSwipeDismiss = enableSwipeDismiss,
  80. onDismissRequest = onDismissRequest,
  81. ) {
  82. val contentPadding = if (isTabletUi) {
  83. PaddingValues()
  84. } else {
  85. WindowInsets.navigationBars.only(WindowInsetsSides.Bottom).asPaddingValues()
  86. }
  87. content(contentPadding)
  88. }
  89. }