ControlCenter.kt 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package eu.mjdev.desktop.components.controlcenter
  2. import androidx.compose.animation.*
  3. import androidx.compose.foundation.background
  4. import androidx.compose.foundation.clickable
  5. import androidx.compose.foundation.gestures.Orientation.Horizontal
  6. import androidx.compose.foundation.layout.*
  7. import androidx.compose.foundation.lazy.LazyColumn
  8. import androidx.compose.foundation.lazy.itemsIndexed
  9. import androidx.compose.foundation.shape.RoundedCornerShape
  10. import androidx.compose.material.Divider
  11. import androidx.compose.material.Icon
  12. import androidx.compose.runtime.*
  13. import androidx.compose.ui.Alignment
  14. import androidx.compose.ui.Modifier
  15. import androidx.compose.ui.graphics.Color
  16. import androidx.compose.ui.unit.Dp
  17. import androidx.compose.ui.unit.DpSize
  18. import androidx.compose.ui.unit.dp
  19. import androidx.compose.ui.window.WindowPosition
  20. import eu.mjdev.desktop.components.shadow.LeftShadow
  21. import eu.mjdev.desktop.components.shadow.RightShadow
  22. import eu.mjdev.desktop.components.sliding.SlidingMenu
  23. import eu.mjdev.desktop.components.sliding.VisibilityState
  24. import eu.mjdev.desktop.components.sliding.VisibilityState.Companion.rememberVisibilityState
  25. import eu.mjdev.desktop.provider.DesktopProvider
  26. import eu.mjdev.desktop.provider.DesktopProvider.Companion.LocalDesktop
  27. import eu.mjdev.desktop.windows.ChromeWindow
  28. import kotlinx.coroutines.CoroutineScope
  29. import kotlinx.coroutines.launch
  30. @Suppress("FunctionName")
  31. @Composable
  32. fun ControlCenter(
  33. api: DesktopProvider = LocalDesktop.current,
  34. backgroundColor: Color = api.currentUser.theme.backgroundColor,
  35. backgroundAlpha: Float = api.currentUser.theme.controlCenterBackgroundAlpha,
  36. shadowColor: Color = backgroundColor, // todo theme
  37. controlCenterDividerColor: Color = backgroundColor,// todo theme
  38. controlCenterExpandedWidth: Dp = api.currentUser.theme.controlCenterExpandedWidth,
  39. controlCenterDividerWidth: Dp = api.currentUser.theme.controlCenterDividerWidth,
  40. controlCenterIconColor: Color = api.currentUser.theme.controlCenterIconColor,
  41. controlCenterIconSize: DpSize = api.currentUser.theme.controlCenterIconSize,
  42. pages: List<ControlCenterPage> = api.controlCenterPages,
  43. pagerState: MutableState<Int> = remember { mutableStateOf(0) },
  44. controlCenterState: VisibilityState = rememberVisibilityState(),
  45. scope: CoroutineScope = rememberCoroutineScope(),
  46. enterAnimation: EnterTransition = fadeIn() + slideInHorizontally(initialOffsetX = { it }),
  47. exitAnimation: ExitTransition = slideOutHorizontally(targetOffsetX = { it }) + fadeOut(),
  48. onFocusChange: (Boolean) -> Unit = {},
  49. ) = ChromeWindow(
  50. visible = true,
  51. enterAnimation = enterAnimation,
  52. exitAnimation = exitAnimation,
  53. position = WindowPosition.Aligned(Alignment.TopEnd),
  54. size = if (controlCenterState.isVisible) {
  55. DpSize(controlCenterExpandedWidth, api.containerSize.height)
  56. } else {
  57. DpSize(controlCenterDividerWidth, api.containerSize.height)
  58. },
  59. onFocusChange = { focused ->
  60. controlCenterState.onFocusChange(focused)
  61. onFocusChange(focused)
  62. }
  63. ) {
  64. SlidingMenu(
  65. modifier = Modifier.fillMaxHeight(),
  66. orientation = Horizontal,
  67. state = controlCenterState,
  68. ) { isVisible ->
  69. if (!isVisible) {
  70. Divider(
  71. modifier = Modifier.fillMaxHeight().width(controlCenterDividerWidth),
  72. color = Color.Transparent,
  73. thickness = controlCenterDividerWidth
  74. )
  75. } else {
  76. LeftShadow(
  77. modifier = Modifier.fillMaxHeight().wrapContentSize(),
  78. color = shadowColor,
  79. contentBackgroundColor = backgroundColor.copy(alpha = backgroundAlpha)
  80. ) {
  81. Row(
  82. modifier = Modifier.fillMaxHeight().wrapContentSize(),
  83. ) {
  84. Divider(
  85. modifier = Modifier.fillMaxHeight().width(controlCenterDividerWidth),
  86. color = controlCenterDividerColor,
  87. thickness = controlCenterDividerWidth
  88. )
  89. Box(
  90. contentAlignment = Alignment.TopEnd
  91. ) {
  92. LazyColumn(
  93. modifier = Modifier
  94. .fillMaxHeight()
  95. .background(backgroundColor)
  96. .padding(8.dp),
  97. verticalArrangement = Arrangement.Top,
  98. horizontalAlignment = Alignment.Start
  99. ) {
  100. itemsIndexed(pages) { idx, page ->
  101. val isSelected = (pagerState.value == idx)
  102. Icon(
  103. modifier = Modifier
  104. .padding(vertical = 8.dp)
  105. .size(controlCenterIconSize)
  106. .background(
  107. color = if (isSelected) Color.White else Color.Transparent,
  108. shape = RoundedCornerShape(8.dp)
  109. )
  110. .clickable {
  111. scope.launch {
  112. pagerState.value = idx
  113. }
  114. },
  115. imageVector = page.icon,
  116. contentDescription = "",
  117. tint = if (isSelected) backgroundColor else controlCenterIconColor
  118. )
  119. }
  120. }
  121. RightShadow(
  122. modifier = Modifier.padding(
  123. end = controlCenterIconSize.width + 16.dp
  124. ).fillMaxHeight().wrapContentSize(),
  125. color = Color.Red,
  126. alpha = 0.3f,
  127. contentBackgroundColor = Color.Transparent
  128. ) {
  129. Row {
  130. Box(
  131. modifier = Modifier.width(controlCenterExpandedWidth),
  132. ) {
  133. pages[pagerState.value].content(backgroundColor)
  134. }
  135. Divider(
  136. modifier = Modifier.fillMaxHeight().width(controlCenterDividerWidth),
  137. color = controlCenterDividerColor,
  138. thickness = controlCenterDividerWidth
  139. )
  140. }
  141. }
  142. Divider(
  143. modifier = Modifier.fillMaxHeight().width(controlCenterDividerWidth),
  144. color = controlCenterDividerColor,
  145. thickness = controlCenterDividerWidth
  146. )
  147. }
  148. }
  149. }
  150. }
  151. }
  152. }