This commit is contained in:
T8RIN
2025-05-16 02:22:18 +03:00
parent 60d3f8b41f
commit 7eebbb5d15
25 changed files with 194 additions and 86 deletions

View File

@ -26,7 +26,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import ru.tech.imageresizershrinker.core.filters.domain.model.BlurEdgeMode
import ru.tech.imageresizershrinker.core.filters.presentation.utils.translatedName
import ru.tech.imageresizershrinker.core.ui.widget.buttons.ToggleGroupButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButtonGroup
@Composable
internal fun EdgeModeSelector(
@ -44,7 +44,7 @@ internal fun EdgeModeSelector(
)
val entries = BlurEdgeMode.entries
ToggleGroupButton(
EnhancedButtonGroup(
inactiveButtonColor = MaterialTheme.colorScheme.surfaceContainerHigh,
items = entries.map { it.translatedName },
selectedIndex = entries.indexOf(value),

View File

@ -35,7 +35,7 @@ import ru.tech.imageresizershrinker.core.filters.domain.model.FadeSide
import ru.tech.imageresizershrinker.core.filters.domain.model.SideFadeParams
import ru.tech.imageresizershrinker.core.filters.presentation.model.UiFilter
import ru.tech.imageresizershrinker.core.filters.presentation.utils.translatedName
import ru.tech.imageresizershrinker.core.ui.widget.buttons.ToggleGroupButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButtonGroup
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedSliderItem
@Composable
@ -88,7 +88,7 @@ internal fun SideFadeRelativeItem(
end = 12.dp,
)
)
ToggleGroupButton(
EnhancedButtonGroup(
inactiveButtonColor = MaterialTheme.colorScheme.surfaceContainerHigh,
items = FadeSide.entries.map { it.translatedName },
selectedIndex = FadeSide.entries.indexOf(sideFade),

View File

@ -27,7 +27,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import ru.tech.imageresizershrinker.core.filters.domain.model.TransferFunc
import ru.tech.imageresizershrinker.core.filters.presentation.utils.translatedName
import ru.tech.imageresizershrinker.core.ui.widget.buttons.ToggleGroupButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButtonGroup
@Composable
internal fun TransferFuncSelector(
@ -46,7 +46,7 @@ internal fun TransferFuncSelector(
val entries = remember {
TransferFunc.entries
}
ToggleGroupButton(
EnhancedButtonGroup(
inactiveButtonColor = MaterialTheme.colorScheme.surfaceContainerHigh,
items = entries.map { it.translatedName },
selectedIndex = entries.indexOf(value),

View File

@ -40,8 +40,8 @@ import ru.tech.imageresizershrinker.core.filters.presentation.model.UiFilter
import ru.tech.imageresizershrinker.core.filters.presentation.utils.translatedName
import ru.tech.imageresizershrinker.core.resources.R
import ru.tech.imageresizershrinker.core.ui.utils.helper.toImageModel
import ru.tech.imageresizershrinker.core.ui.widget.buttons.ToggleGroupButton
import ru.tech.imageresizershrinker.core.ui.widget.controls.selection.ImageSelector
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButtonGroup
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedSliderItem
import ru.tech.imageresizershrinker.core.ui.widget.modifier.ContainerShapeDefaults
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
@ -53,7 +53,7 @@ internal fun FloatPaletteImageModelTripleItem(
onFilterChange: (value: Triple<Float, PaletteTransferSpace, ImageModel>) -> Unit,
previewOnly: Boolean
) {
var sliderState1 by remember { mutableFloatStateOf(value.first.toFloat()) }
var sliderState1 by remember { mutableFloatStateOf(value.first) }
var colorSpace1 by remember { mutableStateOf(value.second) }
var uri1 by remember(value) { mutableStateOf(value.third.data) }
@ -107,7 +107,7 @@ internal fun FloatPaletteImageModelTripleItem(
PaletteTransferSpace.entries
}
}
ToggleGroupButton(
EnhancedButtonGroup(
inactiveButtonColor = MaterialTheme.colorScheme.surfaceContainerHigh,
items = entries.map { it.translatedName },
selectedIndex = entries.indexOf(colorSpace1),

View File

@ -40,9 +40,9 @@ import ru.tech.imageresizershrinker.core.filters.presentation.model.UiFilter
import ru.tech.imageresizershrinker.core.filters.presentation.utils.translatedName
import ru.tech.imageresizershrinker.core.ui.utils.helper.toColor
import ru.tech.imageresizershrinker.core.ui.utils.helper.toModel
import ru.tech.imageresizershrinker.core.ui.widget.buttons.ToggleGroupButton
import ru.tech.imageresizershrinker.core.ui.widget.color_picker.ColorSelectionRowDefaults
import ru.tech.imageresizershrinker.core.ui.widget.controls.selection.ColorRowSelector
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButtonGroup
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedSliderItem
@Composable
@ -124,7 +124,7 @@ internal fun NumberColorModelPopArtTripleItem(
PopArtBlendingMode.entries
}
}
ToggleGroupButton(
EnhancedButtonGroup(
inactiveButtonColor = MaterialTheme.colorScheme.surfaceContainerHigh,
items = entries.map { it.translatedName },
selectedIndex = entries.indexOf(blendMode1),

View File

@ -60,12 +60,12 @@ import ru.tech.imageresizershrinker.core.domain.model.Position
import ru.tech.imageresizershrinker.core.resources.R
import ru.tech.imageresizershrinker.core.ui.utils.state.derivedValueOf
import ru.tech.imageresizershrinker.core.ui.widget.buttons.SupportingButton
import ru.tech.imageresizershrinker.core.ui.widget.buttons.ToggleGroupButton
import ru.tech.imageresizershrinker.core.ui.widget.controls.resize_group.components.BlurRadiusSelector
import ru.tech.imageresizershrinker.core.ui.widget.controls.resize_group.components.UseBlurredBackgroundToggle
import ru.tech.imageresizershrinker.core.ui.widget.controls.selection.ColorRowSelector
import ru.tech.imageresizershrinker.core.ui.widget.controls.selection.PositionSelector
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButtonGroup
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedModalBottomSheet
import ru.tech.imageresizershrinker.core.ui.widget.modifier.ContainerShapeDefaults
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
@ -139,7 +139,7 @@ fun ResizeTypeSelector(
.animateContentSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
ToggleGroupButton(
EnhancedButtonGroup(
modifier = Modifier.padding(start = 3.dp, end = 2.dp),
enabled = enabled,
title = {
@ -198,7 +198,7 @@ fun ResizeTypeSelector(
}
}
}
ToggleGroupButton(
EnhancedButtonGroup(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)

View File

@ -67,7 +67,7 @@ import ru.tech.imageresizershrinker.core.resources.R
import ru.tech.imageresizershrinker.core.resources.icons.QualityHigh
import ru.tech.imageresizershrinker.core.resources.icons.QualityLow
import ru.tech.imageresizershrinker.core.resources.icons.QualityMedium
import ru.tech.imageresizershrinker.core.ui.widget.buttons.ToggleGroupButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButtonGroup
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedChip
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedSliderItem
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
@ -254,7 +254,7 @@ fun QualitySelector(
val items = remember {
Quality.Channels.entries
}
ToggleGroupButton(
EnhancedButtonGroup(
itemCount = items.size,
itemContent = {
Text(items[it].title)

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package ru.tech.imageresizershrinker.core.ui.widget.buttons
package ru.tech.imageresizershrinker.core.ui.widget.enhanced
import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.animation.core.animateDpAsState
@ -39,7 +39,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MotionScheme
import androidx.compose.material3.ProvideTextStyle
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.material3.ToggleButtonDefaults
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
@ -48,10 +47,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
@ -64,7 +59,7 @@ import ru.tech.imageresizershrinker.core.ui.widget.modifier.fadingEdges
import ru.tech.imageresizershrinker.core.ui.widget.text.AutoSizeText
@Composable
fun ToggleGroupButton(
fun EnhancedButtonGroup(
modifier: Modifier = defaultModifier,
enabled: Boolean = true,
items: List<String>,
@ -73,7 +68,7 @@ fun ToggleGroupButton(
onIndexChange: (Int) -> Unit,
inactiveButtonColor: Color = MaterialTheme.colorScheme.surface
) {
ToggleGroupButton(
EnhancedButtonGroup(
enabled = enabled,
items = items,
selectedIndex = selectedIndex,
@ -94,7 +89,7 @@ fun ToggleGroupButton(
}
@Composable
fun ToggleGroupButton(
fun EnhancedButtonGroup(
modifier: Modifier = defaultModifier,
enabled: Boolean,
items: List<String>,
@ -103,7 +98,7 @@ fun ToggleGroupButton(
onIndexChange: (Int) -> Unit,
inactiveButtonColor: Color = MaterialTheme.colorScheme.surface
) {
ToggleGroupButton(
EnhancedButtonGroup(
modifier = modifier,
enabled = enabled,
itemCount = items.size,
@ -124,7 +119,7 @@ fun ToggleGroupButton(
}
@Composable
fun ToggleGroupButton(
fun EnhancedButtonGroup(
modifier: Modifier = defaultModifier,
enabled: Boolean = true,
itemCount: Int,
@ -137,15 +132,14 @@ fun ToggleGroupButton(
isScrollable: Boolean = true
) {
val settingsState = LocalSettingsState.current
val haptics = LocalHapticFeedback.current
val disColor = MaterialTheme.colorScheme.onSurface
val disabledColor = MaterialTheme.colorScheme.onSurface
.copy(alpha = 0.38f)
.compositeOver(MaterialTheme.colorScheme.surface)
ProvideTextStyle(
value = TextStyle(
color = if (!enabled) disColor
value = LocalTextStyle.current.copy(
color = if (!enabled) disabledColor
else Color.Unspecified
)
) {
@ -195,15 +189,10 @@ fun ToggleGroupButton(
}
val selected = index == selectedIndex
val focus = LocalFocusManager.current
ToggleButton(
EnhancedToggleButton(
enabled = enabled,
onCheckedChange = {
focus.clearFocus()
haptics.performHapticFeedback(
HapticFeedbackType.LongPress
)
onIndexChange(index)
},
border = BorderStroke(
@ -221,17 +210,19 @@ fun ToggleGroupButton(
),
checked = selected,
shapes = when (index) {
0 -> ButtonGroupDefaults.connectedLeadingButtonShapes()
itemCount - 1 -> ButtonGroupDefaults.connectedTrailingButtonShapes()
else -> ButtonGroupDefaults.connectedMiddleButtonShapes()
0 -> ButtonGroupDefaults.connectedLeadingButtonShapes(
pressedShape = ButtonDefaults.pressedShape
)
itemCount - 1 -> ButtonGroupDefaults.connectedTrailingButtonShapes(
pressedShape = ButtonDefaults.pressedShape
)
else -> ButtonGroupDefaults.connectedMiddleButtonShapes(
pressedShape = ButtonDefaults.pressedShape
)
},
elevation = ButtonDefaults.buttonElevation(
defaultElevation = elevation,
pressedElevation = elevation,
focusedElevation = elevation,
hoveredElevation = elevation,
disabledElevation = elevation
)
elevation = elevation
) {
itemContent(index)
}

View File

@ -0,0 +1,119 @@
package ru.tech.imageresizershrinker.core.ui.widget.enhanced
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.ToggleButtonColors
import androidx.compose.material3.ToggleButtonDefaults
import androidx.compose.material3.ToggleButtonShapes
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import ru.tech.imageresizershrinker.core.ui.utils.helper.ProvidesValue
import ru.tech.imageresizershrinker.core.ui.widget.modifier.shapeByInteraction
@Composable
fun EnhancedToggleButton(
checked: Boolean,
onCheckedChange: (Boolean) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
shapes: ToggleButtonShapes = ToggleButtonDefaults.shapesFor(ButtonDefaults.MinHeight),
colors: ToggleButtonColors = ToggleButtonDefaults.toggleButtonColors(),
elevation: Dp = 0.dp,
border: BorderStroke? = null,
contentPadding: PaddingValues = ButtonDefaults.contentPaddingFor(ButtonDefaults.MinHeight),
interactionSource: MutableInteractionSource? = null,
content: @Composable RowScope.() -> Unit
) {
val realInteractionSource = interactionSource ?: remember { MutableInteractionSource() }
val containerColor = colors.containerColor(enabled, checked)
val contentColor = colors.contentColor(enabled, checked)
val buttonShape = shapeByInteraction(
shape = if (checked) shapes.checkedShape else shapes.shape,
pressedShape = shapes.pressedShape,
interactionSource = realInteractionSource
)
val haptics = LocalHapticFeedback.current
val focus = LocalFocusManager.current
LocalMinimumInteractiveComponentSize.ProvidesValue(Dp.Unspecified) {
Surface(
checked = checked,
onCheckedChange = {
focus.clearFocus()
haptics.performHapticFeedback(
HapticFeedbackType.LongPress
)
onCheckedChange(it)
},
modifier = modifier.semantics { role = Role.Checkbox },
enabled = enabled,
shape = buttonShape,
color = containerColor,
contentColor = contentColor,
shadowElevation = elevation,
border = border,
interactionSource = realInteractionSource
) {
val mergedStyle = LocalTextStyle.current.merge(MaterialTheme.typography.labelLarge)
CompositionLocalProvider(
LocalContentColor provides contentColor,
LocalTextStyle provides mergedStyle
) {
Row(
modifier = Modifier
.defaultMinSize(minHeight = ToggleButtonDefaults.MinHeight)
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)
}
}
}
}
@Stable
private fun ToggleButtonColors.containerColor(enabled: Boolean, checked: Boolean): Color {
return when {
enabled && checked -> checkedContainerColor
enabled && !checked -> containerColor
else -> disabledContainerColor
}
}
@Stable
private fun ToggleButtonColors.contentColor(enabled: Boolean, checked: Boolean): Color {
return when {
enabled && checked -> checkedContentColor
enabled && !checked -> contentColor
else -> disabledContentColor
}
}

View File

@ -35,7 +35,6 @@ import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.geometry.Size
@ -227,6 +226,7 @@ fun shapeByInteraction(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessMediumLow
),
delay: Long = 300,
enabled: Boolean = true
): Shape {
if (!enabled || interactionSource == null) return shape
@ -240,11 +240,11 @@ fun shapeByInteraction(
mutableStateOf(shape)
}
LaunchedEffect(usePressedShape) {
LaunchedEffect(usePressedShape, shape) {
if (usePressedShape) {
targetShapeState.value = pressedShape
} else {
if (shape is RoundedCornerShape) delay(300)
if (shape is RoundedCornerShape) delay(delay)
targetShapeState.value = shape
}
}
@ -252,12 +252,10 @@ fun shapeByInteraction(
val targetShape = targetShapeState.value
if (targetShape is RoundedCornerShape) {
return key(shape, pressedShape) {
rememberAnimatedShape(
currentShape = targetShape,
animationSpec = animationSpec,
)
}
return rememberAnimatedShape(
currentShape = targetShape,
animationSpec = animationSpec,
)
}
return targetShape