AppsMenu.kt 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package eu.mjdev.desktop.components.appsmenu
  2. import androidx.compose.animation.*
  3. import androidx.compose.foundation.background
  4. import androidx.compose.foundation.border
  5. import androidx.compose.foundation.gestures.Orientation
  6. import androidx.compose.foundation.layout.*
  7. import androidx.compose.foundation.lazy.LazyColumn
  8. import androidx.compose.foundation.lazy.items
  9. import androidx.compose.foundation.shape.RoundedCornerShape
  10. import androidx.compose.runtime.Composable
  11. import androidx.compose.runtime.MutableState
  12. import androidx.compose.runtime.mutableStateOf
  13. import androidx.compose.runtime.remember
  14. import androidx.compose.ui.Alignment
  15. import androidx.compose.ui.Modifier
  16. import androidx.compose.ui.draw.clip
  17. import androidx.compose.ui.graphics.Color
  18. import androidx.compose.ui.layout.onPlaced
  19. import androidx.compose.ui.unit.Dp
  20. import androidx.compose.ui.unit.dp
  21. import androidx.compose.ui.window.WindowPosition
  22. import eu.mjdev.desktop.components.custom.UserAvatar
  23. import eu.mjdev.desktop.components.sliding.VisibilityState
  24. import eu.mjdev.desktop.components.sliding.VisibilityState.Companion.rememberVisibilityState
  25. import eu.mjdev.desktop.extensions.Compose.launchedEffect
  26. import eu.mjdev.desktop.provider.DesktopProvider
  27. import eu.mjdev.desktop.provider.DesktopProvider.Companion.LocalDesktop
  28. import eu.mjdev.desktop.provider.data.App
  29. import eu.mjdev.desktop.provider.data.Category
  30. import eu.mjdev.desktop.windows.ChromeWindow
  31. @Composable
  32. fun AppsMenu(
  33. api: DesktopProvider = LocalDesktop.current,
  34. panelState: VisibilityState = rememberVisibilityState(),
  35. menuState: VisibilityState = rememberVisibilityState(),
  36. appMenuMinWidth: Dp = api.currentUser.theme.appMenuMinWidth,
  37. appMenuMinHeight: Dp = api.currentUser.theme.appMenuMinHeight,
  38. appMenuBackgroundColor: Color = api.currentUser.theme.backgroundColor,
  39. menuPadding: PaddingValues = PaddingValues(api.currentUser.theme.appMenuOuterPadding),// todo
  40. enterAnimation: EnterTransition = fadeIn() + slideInVertically(initialOffsetY = { it }),
  41. exitAnimation: ExitTransition = slideOutVertically(targetOffsetY = { it }) + fadeOut(),
  42. items: MutableState<List<Any>> = remember(api.appsProvider) { mutableStateOf(api.appsProvider.appCategories) },
  43. ) = ChromeWindow(
  44. visible = menuState.isVisible,
  45. enterAnimation = enterAnimation,
  46. exitAnimation = exitAnimation,
  47. position = WindowPosition.Absolute(
  48. panelState.bounds.x,
  49. api.containerSize.height - (panelState.bounds.height + appMenuMinHeight)
  50. )
  51. ) {
  52. Box(
  53. modifier = Modifier
  54. .width(appMenuMinWidth)
  55. .heightIn(
  56. min = appMenuMinHeight,
  57. max = appMenuMinHeight
  58. )
  59. .onPlaced {
  60. // menuState.bounds = it.toDPBounds()
  61. }
  62. ) {
  63. Box(
  64. modifier = Modifier
  65. .fillMaxSize()
  66. .padding(menuPadding)
  67. .background(appMenuBackgroundColor.copy(alpha = 0.7f), RoundedCornerShape(24.dp))
  68. .clip(RoundedCornerShape(24.dp))
  69. .border(2.dp, appMenuBackgroundColor, RoundedCornerShape(24.dp))
  70. ) {
  71. Column(
  72. modifier = Modifier.fillMaxSize()
  73. ) {
  74. UserAvatar(
  75. avatarSize = 64.dp,
  76. backgroundColor = appMenuBackgroundColor,
  77. orientation = Orientation.Horizontal
  78. )
  79. LazyColumn(
  80. modifier = Modifier
  81. .padding(bottom = 48.dp)
  82. .fillMaxSize()
  83. .padding(24.dp)
  84. ) {
  85. when (items.value.firstOrNull()) {
  86. is Category -> {
  87. items(items.value) { item ->
  88. AppsMenuCategory(
  89. category = item as Category,
  90. backgroundColor = appMenuBackgroundColor,
  91. iconTint = Color.White
  92. ) { category ->
  93. items.value = api.appsProvider.categoriesAndApps[category.name]
  94. ?.sortedBy { it.name } ?: emptyList()
  95. }
  96. }
  97. }
  98. is App -> {
  99. items(items.value) { item ->
  100. AppsMenuApp(
  101. app = item as App,
  102. backgroundColor = appMenuBackgroundColor,
  103. iconTint = Color.White
  104. ) { app ->
  105. app?.start()
  106. menuState.hide()
  107. }
  108. }
  109. }
  110. }
  111. }
  112. }
  113. AppsBottomBar(
  114. modifier = Modifier
  115. .fillMaxWidth()
  116. .wrapContentHeight()
  117. .align(Alignment.BottomStart)
  118. .background(appMenuBackgroundColor),
  119. backButtonVisible = items.value.first() is App,// todo
  120. onBackClick = {
  121. items.value = api.appsProvider.appCategories
  122. }
  123. )
  124. }
  125. }
  126. launchedEffect(menuState.isVisible) {
  127. if (!menuState.isVisible) {
  128. items.value = api.appsProvider.appCategories
  129. }
  130. }
  131. }