From cf322147d5e16d816508c9b015eaed73a318275d Mon Sep 17 00:00:00 2001 From: Ax333l Date: Tue, 12 Nov 2024 21:17:02 +0100 Subject: [PATCH] fix: only perform haptics on events --- .../ui/component/haptics/HapticCheckbox.kt | 16 ++-------- .../HapticExtendedFloatingActionButton.kt | 11 ++----- .../haptics/HapticFloatingActionButton.kt | 11 ++----- .../ui/component/haptics/HapticRadioButton.kt | 22 ++++++-------- .../ui/component/haptics/HapticSwitch.kt | 29 ++++++++----------- .../manager/ui/component/haptics/HapticTab.kt | 11 ++----- .../screen/settings/AdvancedSettingsScreen.kt | 8 ++--- .../java/app/revanced/manager/util/Util.kt | 24 ++++++++++++++- 8 files changed, 56 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticCheckbox.kt b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticCheckbox.kt index fb98e40f..fb5453f9 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticCheckbox.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticCheckbox.kt @@ -6,13 +6,12 @@ import androidx.compose.material3.Checkbox import androidx.compose.material3.CheckboxColors import androidx.compose.material3.CheckboxDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalView +import app.revanced.manager.util.withHapticFeedback @Composable -fun HapticCheckbox ( +fun HapticCheckbox( checked: Boolean, onCheckedChange: ((Boolean) -> Unit)?, modifier: Modifier = Modifier, @@ -20,18 +19,9 @@ fun HapticCheckbox ( colors: CheckboxColors = CheckboxDefaults.colors(), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } ) { - val checkedState = remember { mutableStateOf(checked) } - - // Perform haptic feedback - if (checkedState.value != checked) { - val view = LocalView.current - view.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK) - checkedState.value = checked - } - Checkbox( checked = checked, - onCheckedChange = onCheckedChange, + onCheckedChange = onCheckedChange?.withHapticFeedback(HapticFeedbackConstants.CLOCK_TICK), modifier = modifier, enabled = enabled, colors = colors, diff --git a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticExtendedFloatingActionButton.kt b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticExtendedFloatingActionButton.kt index f9d91caf..4fc6ad30 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticExtendedFloatingActionButton.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticExtendedFloatingActionButton.kt @@ -11,7 +11,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.platform.LocalView +import app.revanced.manager.util.withHapticFeedback @Composable fun HapticExtendedFloatingActionButton ( @@ -26,17 +26,10 @@ fun HapticExtendedFloatingActionButton ( elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, ) { - val view = LocalView.current - ExtendedFloatingActionButton( text = text, icon = icon, - onClick = { - // Perform haptic feedback - view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) - - onClick() - }, + onClick = onClick.withHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY), modifier = modifier, expanded = expanded, shape = shape, diff --git a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticFloatingActionButton.kt b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticFloatingActionButton.kt index 0268accc..f4a2e153 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticFloatingActionButton.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticFloatingActionButton.kt @@ -11,7 +11,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.platform.LocalView +import app.revanced.manager.util.withHapticFeedback @Composable fun HapticFloatingActionButton ( @@ -24,15 +24,8 @@ fun HapticFloatingActionButton ( interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, content: @Composable () -> Unit, ) { - val view = LocalView.current - FloatingActionButton( - onClick = { - // Perform haptic feedback - view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) - - onClick() - }, + onClick = onClick.withHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY), modifier = modifier, shape = shape, containerColor = containerColor, diff --git a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticRadioButton.kt b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticRadioButton.kt index 7ac6a7a8..63a9e582 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticRadioButton.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticRadioButton.kt @@ -6,13 +6,12 @@ import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButtonColors import androidx.compose.material3.RadioButtonDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalView @Composable -fun HapticRadioButton ( +fun HapticRadioButton( selected: Boolean, onClick: (() -> Unit)?, modifier: Modifier = Modifier, @@ -20,20 +19,17 @@ fun HapticRadioButton ( colors: RadioButtonColors = RadioButtonDefaults.colors(), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } ) { - val selectedState = remember { mutableStateOf(selected) } - - // Perform haptic feedback - if (selectedState.value != selected) { - if (selected) { - val view = LocalView.current - view.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK) - } - selectedState.value = selected - } + val view = LocalView.current RadioButton( selected = selected, - onClick = onClick, + onClick = onClick?.let { + { + // Perform haptic feedback + if (!selected) view.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK) + it() + } + }, modifier = modifier, enabled = enabled, colors = colors, diff --git a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticSwitch.kt b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticSwitch.kt index fa3e894b..c2491397 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticSwitch.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticSwitch.kt @@ -1,4 +1,5 @@ package app.revanced.manager.ui.component.haptics + import android.os.Build import android.view.HapticFeedbackConstants import androidx.compose.foundation.interaction.MutableInteractionSource @@ -6,37 +7,31 @@ import androidx.compose.material3.Switch import androidx.compose.material3.SwitchColors import androidx.compose.material3.SwitchDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalView @Composable fun HapticSwitch( checked: Boolean, - onCheckedChange: ((Boolean) -> Unit), + onCheckedChange: (Boolean) -> Unit, modifier: Modifier = Modifier, thumbContent: (@Composable () -> Unit)? = null, enabled: Boolean = true, colors: SwitchColors = SwitchDefaults.colors(), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, ) { - val checkedState = remember { mutableStateOf(checked) } - - // Perform haptic feedback - if (checkedState.value != checked) { - val view = LocalView.current - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - view.performHapticFeedback(if (checked) HapticFeedbackConstants.TOGGLE_ON else HapticFeedbackConstants.TOGGLE_OFF) - } else { - view.performHapticFeedback(if (checked) HapticFeedbackConstants.VIRTUAL_KEY else HapticFeedbackConstants.CLOCK_TICK) - } - checkedState.value = checked - } - Switch( checked = checked, - onCheckedChange = onCheckedChange, + onCheckedChange = { newChecked -> + val useNewConstants = Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE + when { + newChecked && useNewConstants -> HapticFeedbackConstants.TOGGLE_ON + newChecked -> HapticFeedbackConstants.VIRTUAL_KEY + !newChecked && useNewConstants -> HapticFeedbackConstants.TOGGLE_OFF + !newChecked -> HapticFeedbackConstants.CLOCK_TICK + } + onCheckedChange(newChecked) + }, modifier = modifier, thumbContent = thumbContent, enabled = enabled, diff --git a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticTab.kt b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticTab.kt index 3b5a11e9..d0676951 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticTab.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/haptics/HapticTab.kt @@ -8,7 +8,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalView +import app.revanced.manager.util.withHapticFeedback @Composable fun HapticTab ( @@ -22,16 +22,9 @@ fun HapticTab ( unselectedContentColor: Color = selectedContentColor, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } ) { - val view = LocalView.current - Tab( selected = selected, - onClick = { - // Perform haptic feedback - view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) - - onClick() - }, + onClick = onClick.withHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY), modifier = modifier, enabled = enabled, text = text, diff --git a/app/src/main/java/app/revanced/manager/ui/screen/settings/AdvancedSettingsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/settings/AdvancedSettingsScreen.kt index fa8cae28..9082f4bb 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/settings/AdvancedSettingsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/settings/AdvancedSettingsScreen.kt @@ -4,6 +4,7 @@ import android.app.ActivityManager import android.content.ClipData import android.content.ClipboardManager import android.os.Build +import android.view.HapticFeedbackConstants import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.ExperimentalFoundationApi @@ -17,9 +18,7 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable 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 import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -35,6 +34,7 @@ import app.revanced.manager.ui.component.settings.IntegerItem import app.revanced.manager.ui.component.settings.SettingsListItem import app.revanced.manager.ui.viewmodel.AdvancedSettingsViewModel import app.revanced.manager.util.toast +import app.revanced.manager.util.withHapticFeedback import org.koin.androidx.compose.koinViewModel @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @@ -52,7 +52,6 @@ fun AdvancedSettingsScreen( activityManager.largeMemoryClass ) } - val haptics = LocalHapticFeedback.current Scaffold( topBar = { @@ -159,13 +158,12 @@ fun AdvancedSettingsScreen( onClick = { }, onLongClickLabel = stringResource(R.string.copy_to_clipboard), onLongClick = { - haptics.performHapticFeedback(HapticFeedbackType.LongPress) clipboard.setPrimaryClip( ClipData.newPlainText("Device Information", deviceContent) ) context.toast(context.getString(R.string.toast_copied_to_clipboard)) - } + }.withHapticFeedback(HapticFeedbackConstants.LONG_PRESS) ), headlineContent = stringResource(R.string.about_device), supportingContent = deviceContent diff --git a/app/src/main/java/app/revanced/manager/util/Util.kt b/app/src/main/java/app/revanced/manager/util/Util.kt index f1de38fd..bc48c54a 100644 --- a/app/src/main/java/app/revanced/manager/util/Util.kt +++ b/app/src/main/java/app/revanced/manager/util/Util.kt @@ -14,6 +14,7 @@ import androidx.annotation.StringRes import androidx.compose.foundation.ScrollState import androidx.compose.foundation.lazy.LazyListState import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.State import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -21,6 +22,7 @@ import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalView import androidx.core.net.toUri import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner @@ -218,4 +220,24 @@ fun ScrollState.isScrollingUp(): State { } val LazyListState.isScrollingUp: Boolean @Composable get() = this.isScrollingUp().value -val ScrollState.isScrollingUp: Boolean @Composable get() = this.isScrollingUp().value \ No newline at end of file +val ScrollState.isScrollingUp: Boolean @Composable get() = this.isScrollingUp().value + +@Composable +@ReadOnlyComposable +fun (() -> R).withHapticFeedback(constant: Int): () -> R { + val view = LocalView.current + return { + view.performHapticFeedback(constant) + this() + } +} + +@Composable +@ReadOnlyComposable +fun ((T) -> R).withHapticFeedback(constant: Int): (T) -> R { + val view = LocalView.current + return { + view.performHapticFeedback(constant) + this(it) + } +} \ No newline at end of file