Skip to content

Commit

Permalink
Improve haptics
Browse files Browse the repository at this point in the history
  • Loading branch information
T8RIN committed Jan 9, 2025
1 parent c4599b9 commit 9553da2
Show file tree
Hide file tree
Showing 60 changed files with 171 additions and 185 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedModalBottomSheet
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.image.Picture
import ru.tech.imageresizershrinker.core.ui.widget.modifier.ContainerShapeDefaults
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.isNetworkAvailable
import ru.tech.imageresizershrinker.core.ui.utils.helper.toImageModel
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.modifier.shimmer
import ru.tech.imageresizershrinker.core.ui.widget.modifier.transparencyChecker
import ru.tech.imageresizershrinker.core.ui.widget.other.LocalToastHostState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ import ru.tech.imageresizershrinker.core.ui.theme.White
import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
import ru.tech.imageresizershrinker.core.ui.utils.helper.toImageModel
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.modifier.shimmer
import ru.tech.imageresizershrinker.core.ui.widget.modifier.transparencyChecker
import ru.tech.imageresizershrinker.core.ui.widget.preferences.PreferenceItemOverload
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ import ru.tech.imageresizershrinker.core.ui.widget.buttons.ShareButton
import ru.tech.imageresizershrinker.core.ui.widget.controls.selection.ImageSelector
import ru.tech.imageresizershrinker.core.ui.widget.dialogs.OneTimeSaveLocationSelectionDialog
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.image.Picture
import ru.tech.imageresizershrinker.core.ui.widget.modifier.ContainerShapeDefaults
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalSim
import ru.tech.imageresizershrinker.core.settings.presentation.provider.rememberEditPresetsController
import ru.tech.imageresizershrinker.core.ui.utils.confetti.LocalConfettiHostState
import ru.tech.imageresizershrinker.core.ui.utils.confetti.rememberConfettiHostState
import ru.tech.imageresizershrinker.core.ui.widget.haptics.rememberCustomHapticFeedback
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.rememberEnhancedHapticFeedback
import ru.tech.imageresizershrinker.core.ui.widget.other.LocalToastHostState
import ru.tech.imageresizershrinker.core.ui.widget.other.ToastHostState
import ru.tech.imageresizershrinker.core.ui.widget.other.rememberToastHostState
Expand All @@ -49,7 +49,7 @@ fun ImageToolboxCompositionLocals(
val editPresetsController = rememberEditPresetsController()
val confettiHostState = rememberConfettiHostState()
val context = LocalContext.current
val customHapticFeedback = rememberCustomHapticFeedback(settingsState.hapticsStrength)
val customHapticFeedback = rememberEnhancedHapticFeedback(settingsState.hapticsStrength)

val values = remember(
toastHostState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable

@Composable
fun SupportingButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedModalBottomSheet
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedModalSheetDragHandle
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedSliderItem
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
import ru.tech.imageresizershrinker.core.ui.widget.palette_selection.PaletteStyleSelection
import ru.tech.imageresizershrinker.core.ui.widget.preferences.PreferenceRowSwitch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.pasteColor
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedAlertDialog
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
import ru.tech.imageresizershrinker.core.ui.widget.modifier.transparencyChecker
import ru.tech.imageresizershrinker.core.ui.widget.text.AutoSizeText
Expand Down Expand Up @@ -332,12 +332,4 @@ private fun getFormattedColor(color: Int): String {
} else {
colorToHexAlpha(Color(color))
}.uppercase()
}

private operator fun String.times(i: Int): String {
var s = ""
repeat(i) {
s += this
}
return s
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -80,7 +79,8 @@ import ru.tech.imageresizershrinker.core.ui.theme.inverse
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.pasteColorFromClipboard
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedModalBottomSheet
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsCombinedClickable
import ru.tech.imageresizershrinker.core.ui.widget.modifier.animateShape
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
import ru.tech.imageresizershrinker.core.ui.widget.modifier.fadingEdges
Expand Down Expand Up @@ -167,7 +167,7 @@ fun ColorSelectionRow(
)
.transparencyChecker()
.background(background, shape)
.combinedClickable(
.hapticsCombinedClickable(
onLongClick = {
context.pasteColorFromClipboard(
onPastedColor = {
Expand All @@ -183,10 +183,11 @@ fun ColorSelectionRow(
}
}
)
},
onClick = {
showColorPicker = true
}
) {
showColorPicker = true
},
),
contentAlignment = Alignment.Center
) {
Icon(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.aspectRatio
Expand Down Expand Up @@ -52,6 +51,7 @@ import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalSet
import ru.tech.imageresizershrinker.core.ui.shapes.MaterialStarShape
import ru.tech.imageresizershrinker.core.ui.theme.inverse
import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container

@OptIn(ExperimentalFoundationApi::class)
Expand Down Expand Up @@ -90,9 +90,7 @@ fun ColorTuplePreview(
borderColor = MaterialTheme.colorScheme.outlineVariant(0.2f),
resultPadding = 0.dp
)
.combinedClickable(
onClick = onClick
)
.hapticsClickable(onClick = onClick)
.padding(3.dp)
.clip(CircleShape),
backgroundColor = Color.Transparent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ import ru.tech.imageresizershrinker.core.ui.utils.helper.sortedByType
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedModalBottomSheet
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.image.Picture
import ru.tech.imageresizershrinker.core.ui.widget.modifier.ContainerShapeDefaults
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
package ru.tech.imageresizershrinker.core.ui.widget.controls.selection

import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -46,7 +45,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
Expand All @@ -60,6 +58,7 @@ import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalSet
import ru.tech.imageresizershrinker.core.ui.shapes.IconShapeContainer
import ru.tech.imageresizershrinker.core.ui.widget.color_picker.ColorSelectionRow
import ru.tech.imageresizershrinker.core.ui.widget.color_picker.ColorSelectionRowDefaults
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsCombinedClickable
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
import ru.tech.imageresizershrinker.core.ui.widget.other.BoxAnimatedVisibility
import ru.tech.imageresizershrinker.core.ui.widget.text.TitleItem
Expand Down Expand Up @@ -142,7 +141,7 @@ fun ColorRowSelector(
},
state = tooltipState,
content = {
val haptics = LocalHapticFeedback.current
LocalHapticFeedback.current
IconShapeContainer(
enabled = true,
content = {
Expand All @@ -159,17 +158,11 @@ fun ColorRowSelector(
LocalSettingsState.current.iconShape?.shape
?: CircleShape
)
.combinedClickable(
.hapticsCombinedClickable(
onLongClick = {
haptics.performHapticFeedback(
HapticFeedbackType.TextHandleMove
)
scope.launch { tooltipState.show() }
},
onClick = {
haptics.performHapticFeedback(
HapticFeedbackType.TextHandleMove
)
scope.launch { tooltipState.show() }
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
Expand All @@ -73,7 +72,7 @@ import ru.tech.imageresizershrinker.core.ui.theme.takeColorFromScheme
import ru.tech.imageresizershrinker.core.ui.utils.helper.toUiPath
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedAlertDialog
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.modifier.ContainerShapeDefaults
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
import ru.tech.imageresizershrinker.core.ui.widget.modifier.fadingEdges
Expand Down Expand Up @@ -252,7 +251,7 @@ fun OneTimeSaveLocationSelectionDialog(
},
directions = setOf(RevealDirection.EndToStart),
swipeableContent = {
val haptics = LocalHapticFeedback.current
LocalHapticFeedback.current
PreferenceItem(
title = title,
subtitle = subtitle,
Expand All @@ -266,9 +265,6 @@ fun OneTimeSaveLocationSelectionDialog(
},
onLongClick = if (item != null) {
{
haptics.performHapticFeedback(
HapticFeedbackType.LongPress
)
scope.launch {
state.animateTo(RevealValue.FullyRevealedStart)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalContainerShape
import ru.tech.imageresizershrinker.core.ui.widget.haptics.hapticsClickable
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container

@Composable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* ImageToolbox is an image editor for android
* Copyright (c) 2024 T8RIN (Malik Mukhametzyanov)
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,7 +17,7 @@

@file:Suppress("DEPRECATION")

package ru.tech.imageresizershrinker.core.ui.widget.haptics
package ru.tech.imageresizershrinker.core.ui.widget.enhanced

import android.annotation.SuppressLint
import android.content.Context
Expand All @@ -28,6 +28,7 @@ import android.view.accessibility.AccessibilityManager
import androidx.compose.foundation.Indication
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
Expand Down Expand Up @@ -64,7 +65,7 @@ private fun Context.isTouchExplorationEnabled(): Boolean {
return accessibilityManager?.isTouchExplorationEnabled == true
}

internal data class CustomHapticFeedback(
internal data class EnhancedHapticFeedback(
val hapticsStrength: Int,
val view: View
) : HapticFeedback {
Expand Down Expand Up @@ -120,13 +121,13 @@ internal data object EmptyHaptics : HapticFeedback {
}

@Composable
fun rememberCustomHapticFeedback(hapticsStrength: Int): HapticFeedback {
fun rememberEnhancedHapticFeedback(hapticsStrength: Int): HapticFeedback {
val view = LocalView.current

val haptics by remember(hapticsStrength) {
derivedStateOf {
if (hapticsStrength == 0) EmptyHaptics
else CustomHapticFeedback(
else EnhancedHapticFeedback(
hapticsStrength = hapticsStrength,
view = view
)
Expand Down Expand Up @@ -173,4 +174,67 @@ fun Modifier.hapticsClickable(
role = role,
onClick = onClick
)
}

fun Modifier.hapticsCombinedClickable(
interactionSource: MutableInteractionSource?,
indication: Indication?,
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onLongClickLabel: String? = null,
onLongClick: (() -> Unit)? = null,
onDoubleClick: (() -> Unit)? = null,
onClick: () -> Unit
) = this.composed {
val haptics = LocalHapticFeedback.current

Modifier.combinedClickable(
interactionSource = interactionSource,
indication = indication,
enabled = enabled,
onClickLabel = onClickLabel,
role = role,
onLongClickLabel = onLongClickLabel,
onLongClick = if (onLongClick != null) {
{
haptics.performHapticFeedback(HapticFeedbackType.LongPress)
onLongClick()
}
} else null,
onDoubleClick = if (onDoubleClick != null) {
{
haptics.performHapticFeedback(HapticFeedbackType.TextHandleMove)
haptics.performHapticFeedback(HapticFeedbackType.LongPress)
onDoubleClick()
}
} else null,
hapticFeedbackEnabled = false,
onClick = {
haptics.performHapticFeedback(HapticFeedbackType.LongPress)
onClick()
}
)
}

fun Modifier.hapticsCombinedClickable(
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onLongClickLabel: String? = null,
onLongClick: (() -> Unit)? = null,
onDoubleClick: (() -> Unit)? = null,
onClick: () -> Unit
) = this.composed {
hapticsCombinedClickable(
interactionSource = null,
indication = LocalIndication.current,
enabled = enabled,
onClickLabel = onClickLabel,
role = role,
onLongClickLabel = onLongClickLabel,
onLongClick = onLongClick,
onDoubleClick = onDoubleClick,
onClick = onClick
)
}
Loading

0 comments on commit 9553da2

Please sign in to comment.