From b1ffc87e69d732a446ed8aed6c68492324f15fe6 Mon Sep 17 00:00:00 2001 From: T8RIN Date: Mon, 23 Dec 2024 20:05:28 +0300 Subject: [PATCH] Add ability to long click markup layer to open context options by #1538 --- .../presentation/MarkupLayersContent.kt | 16 +++++++++- .../presentation/components/EditBox.kt | 29 +++++++++++++------ .../presentation/components/Layer.kt | 7 +++++ .../components/MarkupLayersActions.kt | 4 ++- .../components/MarkupLayersSideMenu.kt | 13 ++++----- .../components/MarkupLayersSideMenuColumn.kt | 2 +- 6 files changed, 51 insertions(+), 20 deletions(-) diff --git a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/MarkupLayersContent.kt b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/MarkupLayersContent.kt index bcbb39b97b..38593db5ab 100644 --- a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/MarkupLayersContent.kt +++ b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/MarkupLayersContent.kt @@ -176,6 +176,10 @@ fun MarkupLayersContent( mutableStateOf(false) } + var isContextOptionsVisible by rememberSaveable { + mutableStateOf(false) + } + val focus = LocalFocusManager.current AdaptiveBottomScaffoldLayoutScreen( autoClearFocus = false, @@ -212,7 +216,11 @@ fun MarkupLayersContent( MarkupLayersActions( component = component, showLayersSelection = showLayersSelection, - onToggleLayersSection = { showLayersSelection = !showLayersSelection } + onToggleLayersSection = { showLayersSelection = !showLayersSelection }, + onToggleLayersSectionQuick = { + showLayersSelection = true + isContextOptionsVisible = true + } ) }, topAppBarPersistentActions = { scaffoldState -> @@ -293,6 +301,10 @@ fun MarkupLayersContent( }, onUpdateLayer = { component.updateLayerAt(index, it) + }, + onShowContextOptions = { + showLayersSelection = true + isContextOptionsVisible = true } ) } @@ -392,6 +404,8 @@ fun MarkupLayersContent( MarkupLayersSideMenu( visible = showLayersSelection, onDismiss = { showLayersSelection = false }, + isContextOptionsVisible = isContextOptionsVisible, + onContextOptionsVisibleChange = { isContextOptionsVisible = it }, onRemoveLayer = component::removeLayer, onReorderLayers = component::reorderLayers, onActivateLayer = component::activateLayer, diff --git a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/EditBox.kt b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/EditBox.kt index 1f1011bb8a..0792f0fab4 100644 --- a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/EditBox.kt +++ b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/EditBox.kt @@ -57,6 +57,7 @@ fun BoxWithConstraintsScope.EditBox( state: EditBoxState, onTap: () -> Unit, modifier: Modifier = Modifier, + onLongTap: (() -> Unit)? = null, shape: Shape = RoundedCornerShape(4.dp), content: @Composable BoxScope.() -> Unit ) { @@ -71,6 +72,7 @@ fun BoxWithConstraintsScope.EditBox( EditBox( modifier = modifier, onTap = onTap, + onLongTap = onLongTap, state = state, parentSize = parentSize, shape = shape, @@ -84,6 +86,7 @@ fun EditBox( onTap: () -> Unit, parentSize: IntegerSize, modifier: Modifier = Modifier, + onLongTap: (() -> Unit)? = null, shape: Shape = RoundedCornerShape(4.dp), content: @Composable BoxScope.() -> Unit ) { @@ -114,6 +117,14 @@ fun EditBox( val tapScale = remember { Animatable(1f) } val scope = rememberCoroutineScope() val haptics = LocalHapticFeedback.current + val animateTap = { + haptics.performHapticFeedback(HapticFeedbackType.LongPress) + scope.launch { + tapScale.animateTo(0.98f) + tapScale.animateTo(1.02f) + tapScale.animateTo(1f) + } + } val borderAlpha by animateFloatAsState(if (state.isActive) 1f else 0f) Box( @@ -131,17 +142,17 @@ fun EditBox( .scale(tapScale.value) .clip(shape) .background(MaterialTheme.colorScheme.primary.copy(0.2f * borderAlpha)) - .pointerInput(onTap) { - detectTapGestures { - onTap() - if (state.isActive) { - scope.launch { - haptics.performHapticFeedback(HapticFeedbackType.LongPress) - tapScale.animateTo(0.95f) - tapScale.animateTo(1.02f) - tapScale.animateTo(1f) + .pointerInput(onTap, animateTap) { + detectTapGestures( + onLongPress = onLongTap?.let { + { + it() + animateTap() } } + ) { + onTap() + if (state.isActive) animateTap() } } .then( diff --git a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/Layer.kt b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/Layer.kt index c3516ee6d1..bff63b72f2 100644 --- a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/Layer.kt +++ b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/Layer.kt @@ -27,6 +27,7 @@ import ru.tech.imageresizershrinker.feature.markup_layers.presentation.component internal fun BoxWithConstraintsScope.Layer( layer: UiMarkupLayer, onActivate: () -> Unit, + onShowContextOptions: () -> Unit, onUpdateLayer: (UiMarkupLayer) -> Unit ) { val type = layer.type @@ -40,6 +41,12 @@ internal fun BoxWithConstraintsScope.Layer( onActivate() } }, + onLongTap = { + if (!layer.state.isActive) { + onActivate() + } + onShowContextOptions() + }, content = { LayerContent( modifier = Modifier.sizeIn( diff --git a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersActions.kt b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersActions.kt index 3fce632feb..ccffbe21c6 100644 --- a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersActions.kt +++ b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersActions.kt @@ -47,7 +47,8 @@ import ru.tech.imageresizershrinker.feature.markup_layers.presentation.screenLog internal fun MarkupLayersActions( component: MarkupLayersComponent, showLayersSelection: Boolean, - onToggleLayersSection: () -> Unit + onToggleLayersSection: () -> Unit, + onToggleLayersSectionQuick: () -> Unit ) { val layerImagePicker = rememberImagePicker { uri: Uri -> component.deactivateAllLayers() @@ -67,6 +68,7 @@ internal fun MarkupLayersActions( if (showLayersSelection) tertiary else Color.Transparent }, + onLongClick = onToggleLayersSectionQuick, onClick = onToggleLayersSection, enabled = component.layers.isNotEmpty() ) { diff --git a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersSideMenu.kt b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersSideMenu.kt index 0815662e98..841083d8e9 100644 --- a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersSideMenu.kt +++ b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersSideMenu.kt @@ -48,9 +48,7 @@ import androidx.compose.material3.Surface import androidx.compose.runtime.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -67,6 +65,8 @@ import ru.tech.imageresizershrinker.feature.markup_layers.presentation.component internal fun MarkupLayersSideMenu( visible: Boolean, onDismiss: () -> Unit, + isContextOptionsVisible: Boolean, + onContextOptionsVisibleChange: (Boolean) -> Unit, onRemoveLayer: (UiMarkupLayer) -> Unit, onReorderLayers: (List) -> Unit, onActivateLayer: (UiMarkupLayer) -> Unit, @@ -145,12 +145,9 @@ internal fun MarkupLayersSideMenu( } Spacer(Modifier.weight(1f)) Box { - var showContextOptions by rememberSaveable(activeLayer) { - mutableStateOf(false) - } EnhancedIconButton( onClick = { - showContextOptions = true + onContextOptionsVisibleChange(true) }, enabled = activeLayer != null ) { @@ -160,8 +157,8 @@ internal fun MarkupLayersSideMenu( ) } MarkupLayersContextActions( - visible = showContextOptions, - onDismiss = { showContextOptions = false }, + visible = isContextOptionsVisible && activeLayer != null, + onDismiss = { onContextOptionsVisibleChange(false) }, onCopyLayer = { activeLayer?.let(onCopyLayer) }, diff --git a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersSideMenuColumn.kt b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersSideMenuColumn.kt index 18f3e03bf3..0974656098 100644 --- a/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersSideMenuColumn.kt +++ b/feature/markup-layers/src/main/java/ru/tech/imageresizershrinker/feature/markup_layers/presentation/components/MarkupLayersSideMenuColumn.kt @@ -185,7 +185,7 @@ internal fun MarkupLayersSideMenuColumn( modifier = Modifier.matchParentSize(), alpha = borderAlpha, scale = 1f, - shape = androidx.compose.foundation.shape.RoundedCornerShape(4.dp) + shape = RoundedCornerShape(4.dp) ) } Spacer(Modifier.width(8.dp))