Skip to content

Commit

Permalink
library: Opt MiuixPopupUtil
Browse files Browse the repository at this point in the history
  • Loading branch information
YuKongA committed Oct 11, 2024
1 parent ee58ec8 commit a81392e
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 53 deletions.
22 changes: 6 additions & 16 deletions composeApp/src/commonMain/kotlin/component/TextComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,7 @@ fun dialog(showDialog: MutableState<Boolean>) {
SuperDialog(
title = "Dialog 1",
summary = "Summary",
show = showDialog,
onDismissRequest = {
showDialog.value = false
},
show = showDialog
) {
TextField(
modifier = Modifier.padding(bottom = 16.dp),
Expand All @@ -320,8 +317,7 @@ fun dialog(showDialog: MutableState<Boolean>) {
modifier = Modifier.weight(1f),
text = "Cancel",
onClick = {
dismissDialog()
showDialog.value = false
dismissDialog(showDialog)
}
)
Spacer(Modifier.width(20.dp))
Expand All @@ -330,8 +326,7 @@ fun dialog(showDialog: MutableState<Boolean>) {
text = "Confirm",
submit = true,
onClick = {
dismissDialog()
showDialog.value = false
dismissDialog(showDialog)
}
)
}
Expand All @@ -350,10 +345,7 @@ fun dialog2(showDialog: MutableState<Boolean>) {
SuperDialog(
title = "Dialog 2",
backgroundColor = MiuixTheme.colorScheme.background,
show = showDialog,
onDismissRequest = {
showDialog.value = false
},
show = showDialog
) {
Card {
SuperDropdown(
Expand All @@ -372,8 +364,7 @@ fun dialog2(showDialog: MutableState<Boolean>) {
modifier = Modifier.weight(1f),
text = "Cancel",
onClick = {
dismissDialog()
showDialog.value = false
dismissDialog(showDialog)
}
)
Spacer(Modifier.width(20.dp))
Expand All @@ -382,8 +373,7 @@ fun dialog2(showDialog: MutableState<Boolean>) {
text = "Confirm",
submit = true,
onClick = {
dismissDialog()
showDialog.value = false
dismissDialog(showDialog)
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import top.yukonga.miuix.kmp.basic.Text
import top.yukonga.miuix.kmp.theme.MiuixTheme
import top.yukonga.miuix.kmp.utils.BackHandler
import top.yukonga.miuix.kmp.utils.MiuixPopupUtil.Companion.dismissDialog
import top.yukonga.miuix.kmp.utils.MiuixPopupUtil.Companion.isDialogShowing
import top.yukonga.miuix.kmp.utils.getRoundedCorner
import top.yukonga.miuix.kmp.utils.getWindowSize
import top.yukonga.miuix.kmp.utils.squircleshape.SquircleShape
Expand All @@ -47,7 +48,7 @@ import top.yukonga.miuix.kmp.utils.squircleshape.SquircleShape
* @param summary The summary of the [SuperDialog].
* @param summaryColor The color of the summary.
* @param backgroundColor The background color of the [SuperDialog].
* @param show The state of the [SuperDialog].
* @param show The show state of the [SuperDialog].
* @param onDismissRequest The callback when the [SuperDialog] is dismissed.
* @param outsideMargin The margin outside the [SuperDialog].
* @param insideMargin The margin inside the [SuperDialog].
Expand All @@ -63,7 +64,7 @@ fun SuperDialog(
summaryColor: Color = MiuixTheme.colorScheme.onSurfaceVariantDialog,
backgroundColor: Color = MiuixTheme.colorScheme.surfaceVariant,
show: MutableState<Boolean>,
onDismissRequest: () -> Unit,
onDismissRequest: (() -> Unit)? = null,
outsideMargin: DpSize = DpSize(12.dp, 12.dp),
insideMargin: Dp = 24.dp,
defaultWindowInsetsPadding: Boolean = true,
Expand All @@ -85,9 +86,9 @@ fun SuperDialog(
}
}

BackHandler(enabled = show.value) {
dismissDialog()
onDismissRequest()
BackHandler(enabled = isDialogShowing()) {
dismissDialog(show)
onDismissRequest?.invoke()
}

Box(
Expand All @@ -102,8 +103,8 @@ fun SuperDialog(
.pointerInput(Unit) {
detectTapGestures(
onTap = {
dismissDialog()
onDismissRequest()
dismissDialog(show)
onDismissRequest?.invoke()
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
Expand Down Expand Up @@ -64,6 +63,7 @@ import top.yukonga.miuix.kmp.icon.icons.Check
import top.yukonga.miuix.kmp.theme.MiuixTheme
import top.yukonga.miuix.kmp.utils.BackHandler
import top.yukonga.miuix.kmp.utils.MiuixPopupUtil.Companion.dismissPopup
import top.yukonga.miuix.kmp.utils.MiuixPopupUtil.Companion.isPopupShowing
import top.yukonga.miuix.kmp.utils.MiuixPopupUtil.Companion.showPopup
import top.yukonga.miuix.kmp.utils.getWindowSize
import top.yukonga.miuix.kmp.utils.squircleshape.SquircleShape
Expand Down Expand Up @@ -103,12 +103,14 @@ fun SuperDropdown(
enabled: Boolean = true
) {
val isDropdownExpanded = remember { mutableStateOf(false) }

if (!dropdownStates.contains(isDropdownExpanded)) dropdownStates.add(isDropdownExpanded)
LaunchedEffect(isDropdownExpanded.value) {
if (isDropdownExpanded.value) {
dropdownStates.forEach { state -> if (state == isDropdownExpanded) state.value = false }
dropdownStates.forEach { state -> if (state != isDropdownExpanded) state.value = false }
}
}

val hapticFeedback = LocalHapticFeedback.current
val density = LocalDensity.current
var alignLeft by rememberSaveable { mutableStateOf(true) }
Expand All @@ -133,8 +135,15 @@ fun SuperDropdown(
)
val insideHeightPx by rememberUpdatedState(with(density) { insideMargin.height.toPx() }.roundToInt())

BackHandler(enabled = isPopupShowing()) {
dismissPopup(isDropdownExpanded)
}

BasicComponent(
onClick = { isDropdownExpanded.value = enabled },
onClick = {
isDropdownExpanded.value = enabled
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
},
modifier = modifier
.pointerInput(Unit) {
awaitPointerEventScope {
Expand Down Expand Up @@ -178,15 +187,7 @@ fun SuperDropdown(
},
enabled = enabled
)
BackHandler(
enabled = isDropdownExpanded.value
) {
dismissPopup()
isDropdownExpanded.value = false
}

if (isDropdownExpanded.value) {
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
showPopup(
content = {
Box(
Expand All @@ -198,10 +199,11 @@ fun SuperDropdown(
}
.fillMaxSize()
.pointerInput(Unit) {
detectTapGestures(onTap = {
dismissPopup()
isDropdownExpanded.value = false
})
detectTapGestures(
onTap = {
dismissPopup(isDropdownExpanded)
}
)
}
.offset(y = offsetPx.dp / density.density)
) {
Expand All @@ -228,22 +230,21 @@ fun SuperDropdown(
.align(if (alignLeft && !alwaysRight) AbsoluteAlignment.TopLeft else AbsoluteAlignment.TopRight)
.graphicsLayer(
shadowElevation = 18f,
shape = SquircleShape(18.dp),
clip = false
shape = SquircleShape(18.dp)
)
.clip(SquircleShape(18.dp))
.background(MiuixTheme.colorScheme.surface)
) {
item {
items.forEachIndexed { index, option ->
DropdownImpl(
options = items,
text = option,
optionSize = items.size,
isSelected = items[selectedIndex] == option,
onSelectedIndexChange = {
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
onSelectedIndexChange(it)
dismissPopup()
isDropdownExpanded.value = false
dismissPopup(isDropdownExpanded)
},
textWidthDp = textWidthDp,
index = index
Expand All @@ -260,23 +261,24 @@ fun SuperDropdown(
/**
* The implementation of the dropdown.
*
* @param options The options of the dropdown.
* @param text The text of the current option.
* @param optionSize The size of the options.
* @param isSelected Whether the option is selected.
* @param index The index of the current option in the options.
* @param onSelectedIndexChange The callback when the index is selected.
* @param textWidthDp The maximum width of text in options.
*/
@Composable
fun DropdownImpl(
options: List<String>,
text: String,
optionSize: Int,
isSelected: Boolean,
index: Int,
onSelectedIndexChange: (Int) -> Unit,
textWidthDp: Dp?
) {
val dropdownInteractionSource = remember { MutableInteractionSource() }
val additionalTopPadding = if (index == 0) 24.dp else 14.dp
val additionalBottomPadding = if (index == options.size - 1) 24.dp else 14.dp
val additionalBottomPadding = if (index == optionSize - 1) 24.dp else 14.dp
val textColor = if (isSelected) {
MiuixTheme.colorScheme.onTertiaryContainer
} else {
Expand Down Expand Up @@ -305,7 +307,7 @@ fun DropdownImpl(
) {
Text(
modifier = Modifier.width(textWidthDp ?: 50.dp),
text = options[index],
text = text,
fontSize = 15.sp,
fontWeight = FontWeight.Medium,
color = textColor,
Expand Down Expand Up @@ -350,8 +352,7 @@ fun calculateOffsetPx(
}
}


/**
* Only one dropdown is allowed to be displayed at a time.
*/
val dropdownStates = mutableStateListOf<MutableState<Boolean>>()
val dropdownStates = mutableStateListOf<MutableState<Boolean>>()
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.zIndex
Expand Down Expand Up @@ -39,16 +40,28 @@ class MiuixPopupUtil {
fun showDialog(
content: (@Composable () -> Unit)? = null,
) {
isPopupShowing.value = false
if (isDialogShowing.value) return
isDialogShowing.value = true
dialogContext.value = content
}

/**
* Check if the dialog is showing.
*/
fun isDialogShowing(): Boolean {
return isDialogShowing.value
}

/**
* Dismiss the dialog.
*
* @param show The show state of the dialog.
*/
fun dismissDialog() {
fun dismissDialog(
show: MutableState<Boolean>,
) {
isDialogShowing.value = false
show.value = false
}

/**
Expand All @@ -60,15 +73,28 @@ class MiuixPopupUtil {
fun showPopup(
content: (@Composable () -> Unit)? = null,
) {
if (isPopupShowing.value) return
isPopupShowing.value = true
popupContext.value = content
}

/**
* Check if the popup is showing.
*/
fun isPopupShowing(): Boolean {
return isPopupShowing.value
}

/**
* Dismiss the popup.
*
* @param show The show state of the popup.
*/
fun dismissPopup() {
fun dismissPopup(
show: MutableState<Boolean>,
) {
isPopupShowing.value = false
show.value = false
}

/**
Expand Down

0 comments on commit a81392e

Please sign in to comment.