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

Commit 47b7029b authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Making haptics in new volume dialog slider continuous." into main

parents c22e789a ad58b2d2
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -192,7 +192,11 @@ fun VolumeSlider(
                        hapticsViewModelFactory?.let {
                            Haptics.Enabled(
                                hapticsViewModelFactory = it,
                                hapticFilter = state.hapticFilter,
                                hapticConfigs =
                                    VolumeHapticsConfigsProvider.discreteConfigs(
                                        state.valueRange.stepSize(),
                                        state.hapticFilter,
                                    ),
                                orientation = Orientation.Horizontal,
                            )
                        } ?: Haptics.Disabled,
@@ -372,16 +376,15 @@ private fun setUpHapticsViewModel(
    hapticsViewModelFactory: SliderHapticsViewModel.Factory?,
): SliderHapticsViewModel? {
    return hapticsViewModelFactory?.let {
        val configs =
            VolumeHapticsConfigsProvider.discreteConfigs(valueRange.stepSize(), hapticFilter)
        rememberViewModel(traceName = "SliderHapticsViewModel") {
                it.create(
                    interactionSource,
                    valueRange,
                    Orientation.Horizontal,
                    VolumeHapticsConfigsProvider.sliderHapticFeedbackConfig(
                        valueRange,
                        hapticFilter,
                    ),
                    VolumeHapticsConfigsProvider.seekableSliderTrackerConfig,
                    configs.hapticFeedbackConfig,
                    configs.sliderTrackerConfig,
                )
            }
            .also { hapticsViewModel ->
@@ -399,3 +402,5 @@ private fun setUpHapticsViewModel(
            }
    }
}

private fun ClosedFloatingPointRange<Float>.stepSize(): Float = 1f / (endInclusive - start)
+5 −1
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
import com.android.systemui.volume.dialog.sliders.ui.compose.SliderTrack
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderViewModel
import com.android.systemui.volume.haptics.ui.VolumeHapticsConfigsProvider
import com.android.systemui.volume.ui.compose.slider.AccessibilityParams
import com.android.systemui.volume.ui.compose.slider.Haptics
import com.android.systemui.volume.ui.compose.slider.Slider
@@ -130,7 +131,10 @@ private fun VolumeDialogSlider(
            hapticsViewModelFactory?.let {
                Haptics.Enabled(
                    hapticsViewModelFactory = it,
                    hapticFilter = SliderHapticFeedbackFilter(),
                    hapticConfigs =
                        VolumeHapticsConfigsProvider.continuousConfigs(
                            SliderHapticFeedbackFilter()
                        ),
                    orientation = Orientation.Vertical,
                )
            } ?: Haptics.Disabled,
+50 −18
Original line number Diff line number Diff line
@@ -22,23 +22,55 @@ import com.android.systemui.haptics.slider.SliderHapticFeedbackFilter

object VolumeHapticsConfigsProvider {

    fun sliderHapticFeedbackConfig(
        valueRange: ClosedFloatingPointRange<Float>,
        filter: SliderHapticFeedbackFilter = SliderHapticFeedbackFilter(),
    ): SliderHapticFeedbackConfig {
        val sliderStepSize = 1f / (valueRange.endInclusive - valueRange.start)
        return SliderHapticFeedbackConfig(
    fun discreteConfigs(stepSize: Float, filter: SliderHapticFeedbackFilter): VolumeHapticsConfigs =
        provideConfigs(stepSize, filter)

    fun continuousConfigs(filter: SliderHapticFeedbackFilter): VolumeHapticsConfigs =
        provideConfigs(stepSize = 0f, filter)

    private fun provideConfigs(
        stepSize: Float,
        filter: SliderHapticFeedbackFilter,
    ): VolumeHapticsConfigs {
        val hapticFeedbackConfig: SliderHapticFeedbackConfig
        val trackerConfig: SeekableSliderTrackerConfig
        if (stepSize == 0f) {
            // Create a set of continuous configs
            hapticFeedbackConfig =
                SliderHapticFeedbackConfig(
                    additionalVelocityMaxBump = 0.1f,
                    deltaProgressForDragThreshold = 0.05f,
                    numberOfLowTicks = 4,
                    maxVelocityToScale = 0.5f, /* slider progress(from 0 to 1) per sec */
                    filter = filter,
                )
            trackerConfig =
                SeekableSliderTrackerConfig(
                    lowerBookendThreshold = 0.01f,
                    upperBookendThreshold = 0.99f,
                )
        } else {
            // Create a set of discrete configs
            hapticFeedbackConfig =
                SliderHapticFeedbackConfig(
                    lowerBookendScale = 0.2f,
                    progressBasedDragMinScale = 0.2f,
                    progressBasedDragMaxScale = 0.5f,
                    deltaProgressForDragThreshold = 0f,
                    additionalVelocityMaxBump = 0.2f,
                    maxVelocityToScale = 0.1f, /* slider progress(from 0 to 1) per sec */
            sliderStepSize = sliderStepSize,
                    sliderStepSize = stepSize,
                    filter = filter,
                )
    }

    val seekableSliderTrackerConfig =
            trackerConfig =
                SeekableSliderTrackerConfig(lowerBookendThreshold = 0f, upperBookendThreshold = 1f)
        }
        return VolumeHapticsConfigs(hapticFeedbackConfig, trackerConfig)
    }
}

// A collection of configuration parameters for the haptics in the slider
data class VolumeHapticsConfigs(
    val hapticFeedbackConfig: SliderHapticFeedbackConfig,
    val sliderTrackerConfig: SeekableSliderTrackerConfig,
)
+15 −21
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.ProgressBarRangeInfo
import androidx.compose.ui.semantics.SemanticsPropertyReceiver
@@ -46,14 +45,10 @@ import androidx.compose.ui.semantics.disabled
import androidx.compose.ui.semantics.progressBarRangeInfo
import androidx.compose.ui.semantics.setProgress
import androidx.compose.ui.semantics.stateDescription
import com.android.systemui.haptics.slider.SliderHapticFeedbackFilter
import com.android.systemui.haptics.slider.compose.ui.SliderHapticsViewModel
import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.volume.haptics.ui.VolumeHapticsConfigsProvider
import com.android.systemui.volume.haptics.ui.VolumeHapticsConfigs
import kotlin.math.round
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map

@Composable
fun Slider(
@@ -95,7 +90,7 @@ fun Slider(
    val sliderState =
        remember(valueRange) { SliderState(value = animatedValue, valueRange = valueRange) }
    val valueChange: (Float) -> Unit = { newValue ->
        hapticsViewModel?.onValueChange(newValue)
        hapticsViewModel?.addVelocityDataPoint(newValue)
        onValueChanged(newValue)
    }
    val semantics =
@@ -193,23 +188,22 @@ private fun Haptics.createViewModel(
                            interactionSource,
                            valueRange,
                            orientation,
                            VolumeHapticsConfigsProvider.sliderHapticFeedbackConfig(
                                valueRange,
                                hapticFilter,
                            ),
                            VolumeHapticsConfigsProvider.seekableSliderTrackerConfig,
                            hapticConfigs.hapticFeedbackConfig,
                            hapticConfigs.sliderTrackerConfig,
                        )
                    }
                    .also { hapticsViewModel ->
                        var lastDiscreteStep by remember { mutableFloatStateOf(value) }
                        var lastValue by remember { mutableFloatStateOf(value) }
                        LaunchedEffect(value) {
                            snapshotFlow { value }
                                .map { round(it) }
                                .filter { it != lastDiscreteStep }
                                .distinctUntilChanged()
                                .collect { discreteStep ->
                                    lastDiscreteStep = discreteStep
                                    hapticsViewModel.onValueChange(discreteStep)
                            val roundedValue =
                                if (hapticConfigs.hapticFeedbackConfig.sliderStepSize != 0f) {
                                    round(value)
                                } else {
                                    value
                                }
                            if (roundedValue != lastValue) {
                                lastValue = roundedValue
                                hapticsViewModel.onValueChange(roundedValue)
                            }
                        }
                    }
@@ -228,7 +222,7 @@ sealed interface Haptics {

    data class Enabled(
        val hapticsViewModelFactory: SliderHapticsViewModel.Factory,
        val hapticFilter: SliderHapticFeedbackFilter,
        val hapticConfigs: VolumeHapticsConfigs,
        val orientation: Orientation,
    ) : Haptics
}