Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d5f04ea authored by Juan Sebastian Martinez's avatar Juan Sebastian Martinez
Browse files

Avoiding an extra coroutine on continuous volume panel slider haptics.

Continuous slider haptics require a more responsive behavior and more
logic and computations. We can coptimize the overall UIs if we avoid
extra LaunchedEffects by calling the SliderHapticsViewModel on existing
coroutines that already respond to the slider value change.

Test: manual. Verified continuous haptics are delivered by volume panel
  sliders
Flag: NONE bugfix
Bug: 422308419
Change-Id: Ie312a565cd4da82da0bb8bc1f98960742eabefe7
parent 224a5afc
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -38,8 +38,8 @@ object VolumeHapticsConfigsProvider {
            // Create a set of continuous configs
            hapticFeedbackConfig =
                SliderHapticFeedbackConfig(
                    additionalVelocityMaxBump = 0.2f,
                    deltaProgressForDragThreshold = 0.01f,
                    additionalVelocityMaxBump = 0.1f,
                    deltaProgressForDragThreshold = 0.05f,
                    numberOfLowTicks = 4,
                    maxVelocityToScale = 0.5f, /* slider progress(from 0 to 1) per sec */
                    filter = filter,
+18 −13
Original line number Diff line number Diff line
@@ -87,6 +87,8 @@ fun Slider(
    val coroutineScope = rememberCoroutineScope()
    var animationJob: Job? by remember { mutableStateOf(null) }
    val sliderState = remember(valueRange) { SliderState(value = value, valueRange = valueRange) }
    val hapticsViewModel =
        haptics.rememberViewModel(sliderState.value, valueRange, interactionSource)
    LaunchedEffect(value) {
        if (!sliderState.isDragging && sliderState.value != value) {
            animationJob =
@@ -97,19 +99,23 @@ fun Slider(
                        animationSpec = animationSpec,
                    ) { animatedValue, _ ->
                        sliderState.value = animatedValue
                        if (haptics is Haptics.Enabled && !haptics.isDiscrete()) {
                            hapticsViewModel?.onValueChange(animatedValue)
                        }
                    }
                }
        }
    }

    val hapticsViewModel =
        haptics.rememberViewModel(sliderState.value, valueRange, interactionSource)
    val valueChange: (Float) -> Unit = { newValue ->
        if (sliderState.isDragging) {
            animationJob?.cancel()
            sliderState.value = newValue
        }
        hapticsViewModel?.addVelocityDataPoint(newValue)
        if (haptics is Haptics.Enabled && !haptics.isDiscrete()) {
            hapticsViewModel?.onValueChange(newValue)
        }
        onValueChanged(newValue)
    }
    val semantics =
@@ -224,14 +230,10 @@ private fun Haptics.rememberViewModel(
                        )
                    }
                    .also { hapticsViewModel ->
                        if (isDiscrete()) {
                            var lastValue by remember { mutableFloatStateOf(value) }
                            LaunchedEffect(value) {
                            val roundedValue =
                                if (hapticConfigs.hapticFeedbackConfig.sliderStepSize != 0f) {
                                    round(value)
                                } else {
                                    value
                                }
                                val roundedValue = round(value)
                                if (roundedValue != lastValue) {
                                    lastValue = roundedValue
                                    hapticsViewModel.onValueChange(roundedValue)
@@ -242,6 +244,7 @@ private fun Haptics.rememberViewModel(
            }
        }
    }
}

data class AccessibilityParams(
    val contentDescription: String,
@@ -255,5 +258,7 @@ sealed interface Haptics {
        val hapticsViewModelFactory: SliderHapticsViewModel.Factory,
        val hapticConfigs: VolumeHapticsConfigs,
        val orientation: Orientation,
    ) : Haptics
    ) : Haptics {
        fun isDiscrete(): Boolean = hapticConfigs.hapticFeedbackConfig.sliderStepSize != 0f
    }
}