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

Commit 1f8b39b0 authored by Juan Sebastian Martinez's avatar Juan Sebastian Martinez Committed by Android (Google) Code Review
Browse files

Merge "Relocating the animator in the QSLongPressEffect" into main

parents ef8f2178 bf938d7e
Loading
Loading
Loading
Loading
+146 −181
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.testing.TestableLooper.RunWithLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.AnimatorTestRule
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -32,19 +31,14 @@ import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule

@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper(setAsMainLooper = true)
class QSLongPressEffectTest : SysuiTestCase() {

    @Rule @JvmField val mMockitoRule: MockitoRule = MockitoJUnit.rule()
    @get:Rule val animatorTestRule = AnimatorTestRule(this)
    private val kosmos = testKosmos()
    private val vibratorHelper = kosmos.vibratorHelper

@@ -67,58 +61,28 @@ class QSLongPressEffectTest : SysuiTestCase() {
                vibratorHelper,
                kosmos.keyguardInteractor,
            )
        longPressEffect.initializeEffect(effectDuration)
    }

    @Test
    fun onReset_whileIdle_resetsEffect() = testWithScope {
        // GIVEN a call to reset
        longPressEffect.resetEffect()

        // THEN the effect remains idle and has not been initialized
        val state by collectLastValue(longPressEffect.state)
        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
        assertThat(longPressEffect.hasInitialized).isFalse()
    }

    @Test
    fun onReset_whileRunning_resetsEffect() = testWhileRunning {
        // GIVEN a call to reset
        longPressEffect.resetEffect()

        // THEN the effect remains idle and has not been initialized
        val state by collectLastValue(longPressEffect.state)
        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
        assertThat(longPressEffect.hasInitialized).isFalse()
    }

    @Test
    fun onInitialize_withNegativeDuration_doesNotInitialize() = testWithScope {
        // GIVEN an effect that has reset
        longPressEffect.resetEffect()

    fun onInitialize_withNegativeDuration_doesNotInitialize() =
        testWithScope(false) {
            // WHEN attempting to initialize with a negative duration
            val couldInitialize = longPressEffect.initializeEffect(-1)

            // THEN the effect can't initialized and remains reset
        val state by collectLastValue(longPressEffect.state)
            assertThat(couldInitialize).isFalse()
        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
            assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
            assertThat(longPressEffect.hasInitialized).isFalse()
        }

    @Test
    fun onInitialize_withPositiveDuration_initializes() = testWithScope {
        // GIVEN an effect that has reset
        longPressEffect.resetEffect()

        // WHEN attempting to initialize with a positive duration
        val couldInitialize = longPressEffect.initializeEffect(effectDuration)

        // THEN the effect is initialized
        val state by collectLastValue(longPressEffect.state)
        assertThat(couldInitialize).isTrue()
        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
        assertThat(longPressEffect.hasInitialized).isTrue()
    }

@@ -128,23 +92,23 @@ class QSLongPressEffectTest : SysuiTestCase() {
        longPressEffect.handleActionDown()

        // THEN the effect moves to the TIMEOUT_WAIT state
        val state by collectLastValue(longPressEffect.state)
        assertThat(state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
    }

    @Test
    fun onActionCancel_whileWaiting_goesIdle() = testWhileWaiting {
    fun onActionCancel_whileWaiting_goesIdle() =
        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
            // GIVEN an action cancel occurs
            longPressEffect.handleActionCancel()

            // THEN the effect goes back to idle and does not start
        val state by collectLastValue(longPressEffect.state)
        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
            assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
            assertEffectDidNotStart()
        }

    @Test
    fun onActionUp_whileWaiting_performsClick() = testWhileWaiting {
    fun onActionUp_whileWaiting_performsClick() =
        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
            // GIVEN an action is being collected
            val action by collectLastValue(longPressEffect.actionType)

@@ -157,42 +121,68 @@ class QSLongPressEffectTest : SysuiTestCase() {
        }

    @Test
    fun onWaitComplete_whileWaiting_beginsEffect() = testWhileWaiting {
    fun onWaitComplete_whileWaiting_beginsEffect() =
        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
            // GIVEN the pressed timeout is complete
            longPressEffect.handleTimeoutComplete()

        // THEN the effect starts
        assertEffectStarted()
            // THEN the effect emits the action to start an animator
            val action by collectLastValue(longPressEffect.actionType)
            assertThat(action).isEqualTo(QSLongPressEffect.ActionType.START_ANIMATOR)
        }

    @Test
    fun onActionUp_whileEffectHasBegun_reversesEffect() = testWhileRunning {
        // GIVEN that the effect is at the middle of its completion (progress of 50%)
        animatorTestRule.advanceTimeBy(effectDuration / 2L)
    fun onAnimationStart_whileWaiting_effectBegins() =
        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
            // GIVEN that the animator starts
            longPressEffect.handleAnimationStart()

        // WHEN an action up occurs
            // THEN the effect begins
            assertEffectStarted()
        }

    @Test
    fun onActionUp_whileEffectHasBegun_reversesEffect() =
        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
            // GIVEN an action up occurs
            longPressEffect.handleActionUp()

        // THEN the effect gets reversed at 50% progress
        assertEffectReverses(0.5f)
            // THEN the effect reverses
            assertEffectReverses()
        }

    @Test
    fun onActionCancel_whileEffectHasBegun_reversesEffect() = testWhileRunning {
        // GIVEN that the effect is at the middle of its completion (progress of 50%)
        animatorTestRule.advanceTimeBy(effectDuration / 2L)
    fun onPlayReverseHaptics_reverseHapticsArePlayed() = testWithScope {
        // GIVEN a call to play reverse haptics at the effect midpoint
        val progress = 0.5f
        longPressEffect.playReverseHaptics(progress)

        // THEN the expected texture is played
        val reverseHaptics =
            LongPressHapticBuilder.createReversedEffect(
                progress,
                lowTickDuration,
                effectDuration,
            )
        assertThat(reverseHaptics).isNotNull()
        assertThat(vibratorHelper.hasVibratedWithEffects(reverseHaptics!!)).isTrue()
    }

    @Test
    fun onActionCancel_whileEffectHasBegun_reversesEffect() =
        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
            // WHEN an action cancel occurs
            longPressEffect.handleActionCancel()

        // THEN the effect gets reversed at 50% progress
        assertEffectReverses(0.5f)
            // THEN the effect gets reversed
            assertEffectReverses()
        }

    @Test
    fun onAnimationComplete_keyguardDismissible_effectEndsWithLongPress() = testWhileRunning {
    fun onAnimationComplete_keyguardDismissible_effectEndsWithLongPress() =
        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
            // GIVEN that the animation completes
        animatorTestRule.advanceTimeBy(effectDuration + 10L)
            longPressEffect.handleAnimationComplete()

            // THEN the long-press effect completes with a LONG_PRESS
            assertEffectCompleted(QSLongPressEffect.ActionType.LONG_PRESS)
@@ -200,68 +190,76 @@ class QSLongPressEffectTest : SysuiTestCase() {

    @Test
    fun onAnimationComplete_keyguardNotDismissible_effectEndsWithResetAndLongPress() =
        testWhileRunning {
        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
            // GIVEN that the keyguard is not dismissible
            kosmos.fakeKeyguardRepository.setKeyguardDismissible(false)

            // GIVEN that the animation completes
            animatorTestRule.advanceTimeBy(effectDuration + 10L)
            longPressEffect.handleAnimationComplete()

            // THEN the long-press effect completes with RESET_AND_LONG_PRESS
            assertEffectCompleted(QSLongPressEffect.ActionType.RESET_AND_LONG_PRESS)
        }

    @Test
    fun onActionDown_whileRunningBackwards_resets() = testWhileRunning {
        // GIVEN that the effect is at the middle of its completion (progress of 50%)
        animatorTestRule.advanceTimeBy(effectDuration / 2L)

    fun onActionDown_whileRunningBackwards_cancels() =
        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
            // GIVEN an action cancel occurs and the effect gets reversed
            longPressEffect.handleActionCancel()

            // GIVEN an action down occurs
            longPressEffect.handleActionDown()

        // THEN the effect resets
        assertEffectResets()
            // THEN the effect posts an action to cancel the animator
            val action by collectLastValue(longPressEffect.actionType)
            assertThat(action).isEqualTo(QSLongPressEffect.ActionType.CANCEL_ANIMATOR)
        }

    @Test
    fun onAnimationComplete_whileRunningBackwards_goesToIdle() = testWhileRunning {
        // GIVEN that the effect is at the middle of its completion (progress of 50%)
        animatorTestRule.advanceTimeBy(effectDuration / 2L)
    fun onAnimatorCancel_effectGoesBackToWait() =
        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
            // GIVEN that the animator was cancelled
            longPressEffect.handleAnimationCancel()

            // THEN the state goes to the timeout wait
            assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
        }

    @Test
    fun onAnimationComplete_whileRunningBackwards_goesToIdle() =
        testWhileInState(QSLongPressEffect.State.RUNNING_BACKWARDS) {
            // GIVEN an action cancel occurs and the effect gets reversed
            longPressEffect.handleActionCancel()

        // GIVEN that the animation completes after a sufficient amount of time
        animatorTestRule.advanceTimeBy(effectDuration.toLong())
            // GIVEN that the animation completes
            longPressEffect.handleAnimationComplete()

            // THEN the state goes to [QSLongPressEffect.State.IDLE]
        val state by collectLastValue(longPressEffect.state)
        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
            assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
        }

    private fun testWithScope(test: suspend TestScope.() -> Unit) =
        with(kosmos) { testScope.runTest { test() } }

    private fun testWhileWaiting(test: suspend TestScope.() -> Unit) =
    private fun testWithScope(initialize: Boolean = true, test: suspend TestScope.() -> Unit) =
        with(kosmos) {
            testScope.runTest {
                // GIVEN the TIMEOUT_WAIT state is entered
                longPressEffect.setState(QSLongPressEffect.State.TIMEOUT_WAIT)

                // THEN run the test
                if (initialize) {
                    longPressEffect.initializeEffect(effectDuration)
                }
                test()
            }
        }

    private fun testWhileRunning(test: suspend TestScope.() -> Unit) =
    private fun testWhileInState(
        state: QSLongPressEffect.State,
        initialize: Boolean = true,
        test: suspend TestScope.() -> Unit,
    ) =
        with(kosmos) {
            testScope.runTest {
                // GIVEN that the effect starts after the tap timeout is complete
                longPressEffect.setState(QSLongPressEffect.State.TIMEOUT_WAIT)
                longPressEffect.handleTimeoutComplete()
                if (initialize) {
                    longPressEffect.initializeEffect(effectDuration)
                }
                // GIVEN a state
                longPressEffect.setState(state)

                // THEN run the test
                test()
@@ -270,13 +268,10 @@ class QSLongPressEffectTest : SysuiTestCase() {

    /**
     * Asserts that the effect started by checking that:
     * 1. The effect progress is 0f
     * 2. Initial hint haptics are played
     * 3. The internal state is [QSLongPressEffect.State.RUNNING_FORWARD]
     * 1. Initial hint haptics are played
     * 2. The internal state is [QSLongPressEffect.State.RUNNING_FORWARD]
     */
    private fun TestScope.assertEffectStarted() {
        val effectProgress by collectLastValue(longPressEffect.effectProgress)
        val state by collectLastValue(longPressEffect.state)
    private fun assertEffectStarted() {
        val longPressHint =
            LongPressHapticBuilder.createLongPressHint(
                lowTickDuration,
@@ -284,78 +279,48 @@ class QSLongPressEffectTest : SysuiTestCase() {
                effectDuration,
            )

        assertThat(state).isEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
        assertThat(effectProgress).isEqualTo(0f)
        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
        assertThat(longPressHint).isNotNull()
        assertThat(vibratorHelper.hasVibratedWithEffects(longPressHint!!)).isTrue()
    }

    /**
     * Asserts that the effect did not start by checking that:
     * 1. No effect progress is emitted
     * 2. No haptics are played
     * 3. The internal state is not [QSLongPressEffect.State.RUNNING_BACKWARDS] or
     * 1. No haptics are played
     * 2. The internal state is not [QSLongPressEffect.State.RUNNING_BACKWARDS] or
     *    [QSLongPressEffect.State.RUNNING_FORWARD]
     */
    private fun TestScope.assertEffectDidNotStart() {
        val effectProgress by collectLastValue(longPressEffect.effectProgress)
        val state by collectLastValue(longPressEffect.state)

        assertThat(state).isNotEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
        assertThat(state).isNotEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
        assertThat(effectProgress).isNull()
    private fun assertEffectDidNotStart() {
        assertThat(longPressEffect.state).isNotEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
        assertThat(longPressEffect.state).isNotEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
        assertThat(vibratorHelper.totalVibrations).isEqualTo(0)
    }

    /**
     * Asserts that the effect completes by checking that:
     * 1. The progress is null
     * 2. The final snap haptics are played
     * 3. The internal state goes back to [QSLongPressEffect.State.IDLE]
     * 4. The action to perform on the tile is the action given as a parameter
     * 1. The final snap haptics are played
     * 2. The internal state goes back to [QSLongPressEffect.State.IDLE]
     * 3. The action to perform on the tile is the action given as a parameter
     */
    private fun TestScope.assertEffectCompleted(expectedAction: QSLongPressEffect.ActionType) {
        val action by collectLastValue(longPressEffect.actionType)
        val effectProgress by collectLastValue(longPressEffect.effectProgress)
        val snapEffect = LongPressHapticBuilder.createSnapEffect()
        val state by collectLastValue(longPressEffect.state)

        assertThat(effectProgress).isNull()
        assertThat(snapEffect).isNotNull()
        assertThat(vibratorHelper.hasVibratedWithEffects(snapEffect!!)).isTrue()
        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
        assertThat(action).isEqualTo(expectedAction)
    }

    /**
     * Assert that the effect gets reverted by checking that:
     * 1. The internal state is [QSLongPressEffect.State.RUNNING_BACKWARDS]
     * 2. The reverse haptics plays at the point where the animation was paused
     */
    private fun TestScope.assertEffectReverses(pausedProgress: Float) {
        val reverseHaptics =
            LongPressHapticBuilder.createReversedEffect(
                pausedProgress,
                lowTickDuration,
                effectDuration,
            )
        val state by collectLastValue(longPressEffect.state)

        assertThat(state).isEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
        assertThat(reverseHaptics).isNotNull()
        assertThat(vibratorHelper.hasVibratedWithEffects(reverseHaptics!!)).isTrue()
    }

    /**
     * Asserts that the effect resets by checking that:
     * 1. The effect progress resets to 0
     * 2. The internal state goes back to [QSLongPressEffect.State.TIMEOUT_WAIT]
     * 2. An action to reverse the animator is emitted
     */
    private fun TestScope.assertEffectResets() {
        val effectProgress by collectLastValue(longPressEffect.effectProgress)
        val state by collectLastValue(longPressEffect.state)
    private fun TestScope.assertEffectReverses() {
        val action by collectLastValue(longPressEffect.actionType)

        assertThat(effectProgress).isNull()
        assertThat(state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
        assertThat(action).isEqualTo(QSLongPressEffect.ActionType.REVERSE_ANIMATOR)
    }
}
+40 −71
Original line number Diff line number Diff line
@@ -16,20 +16,14 @@

package com.android.systemui.haptics.qs

import android.animation.ValueAnimator
import android.os.VibrationEffect
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.annotation.VisibleForTesting
import androidx.core.animation.doOnCancel
import androidx.core.animation.doOnEnd
import androidx.core.animation.doOnStart
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.statusbar.VibratorHelper
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine

/**
@@ -50,17 +44,14 @@ constructor(
    keyguardInteractor: KeyguardInteractor,
) {

    private var effectDuration = 0
    var effectDuration = 0
        private set

    /** Current state */
    private var _state = MutableStateFlow(State.IDLE)
    val state = _state.asStateFlow()
    var state = State.IDLE
        private set

    /** Flows for view control and action */
    private val _effectProgress = MutableStateFlow<Float?>(null)
    val effectProgress = _effectProgress.asStateFlow()

    // Actions to perform
    /** Flow for view control and action */
    private val _postedActionType = MutableStateFlow<ActionType?>(null)
    val actionType: Flow<ActionType?> =
        combine(
@@ -85,19 +76,15 @@ constructor(

    private val snapEffect = LongPressHapticBuilder.createSnapEffect()

    private var effectAnimator: ValueAnimator? = null

    val hasInitialized: Boolean
        get() = longPressHint != null && effectAnimator != null
        get() = longPressHint != null

    @VisibleForTesting
    fun setState(state: State) {
        _state.value = state
    fun setState(newState: State) {
        state = newState
    }

    private fun reverse() {
        effectAnimator?.let {
            val pausedProgress = it.animatedFraction
    fun playReverseHaptics(pausedProgress: Float) {
        val effect =
            LongPressHapticBuilder.createReversedEffect(
                pausedProgress,
@@ -106,8 +93,6 @@ constructor(
            )
        vibratorHelper?.cancel()
        vibrate(effect)
            it.reverse()
        }
    }

    private fun vibrate(effect: VibrationEffect?) {
@@ -117,23 +102,23 @@ constructor(
    }

    fun handleActionDown() {
        when (_state.value) {
        when (state) {
            State.IDLE -> {
                setState(State.TIMEOUT_WAIT)
            }
            State.RUNNING_BACKWARDS -> effectAnimator?.cancel()
            State.RUNNING_BACKWARDS -> _postedActionType.value = ActionType.CANCEL_ANIMATOR
            else -> {}
        }
    }

    fun handleActionUp() {
        when (_state.value) {
        when (state) {
            State.TIMEOUT_WAIT -> {
                _postedActionType.value = ActionType.CLICK
                setState(State.IDLE)
            }
            State.RUNNING_FORWARD -> {
                reverse()
                _postedActionType.value = ActionType.REVERSE_ANIMATOR
                setState(State.RUNNING_BACKWARDS)
            }
            else -> {}
@@ -141,44 +126,42 @@ constructor(
    }

    fun handleActionCancel() {
        when (_state.value) {
        when (state) {
            State.TIMEOUT_WAIT -> {
                setState(State.IDLE)
            }
            State.RUNNING_FORWARD -> {
                reverse()
                _postedActionType.value = ActionType.REVERSE_ANIMATOR
                setState(State.RUNNING_BACKWARDS)
            }
            else -> {}
        }
    }

    private fun handleAnimationStart() {
    fun handleAnimationStart() {
        vibrate(longPressHint)
        setState(State.RUNNING_FORWARD)
    }

    /** This function is called both when an animator completes or gets cancelled */
    private fun handleAnimationComplete() {
        if (_state.value == State.RUNNING_FORWARD) {
    fun handleAnimationComplete() {
        if (state == State.RUNNING_FORWARD) {
            vibrate(snapEffect)
            _postedActionType.value = ActionType.LONG_PRESS
            _effectProgress.value = null
        }
        if (_state.value != State.TIMEOUT_WAIT) {
        if (state != State.TIMEOUT_WAIT) {
            // This will happen if the animator did not finish by being cancelled
            setState(State.IDLE)
        }
    }

    private fun handleAnimationCancel() {
        _effectProgress.value = null
    fun handleAnimationCancel() {
        setState(State.TIMEOUT_WAIT)
    }

    fun handleTimeoutComplete() {
        if (_state.value == State.TIMEOUT_WAIT && effectAnimator?.isRunning == false) {
            effectAnimator?.start()
        if (state == State.TIMEOUT_WAIT) {
            _postedActionType.value = ActionType.START_ANIMATOR
        }
    }

@@ -186,18 +169,6 @@ constructor(
        _postedActionType.value = null
    }

    /** Reset the effect by going back to a default [IDLE] state */
    fun resetEffect() {
        if (effectAnimator?.isRunning == true) {
            effectAnimator?.cancel()
        }
        longPressHint = null
        effectAnimator = null
        _effectProgress.value = null
        _postedActionType.value = null
        setState(State.IDLE)
    }

    /**
     * Reset the effect with a new effect duration.
     *
@@ -205,27 +176,21 @@ constructor(
     * @return true if the effect initialized correctly
     */
    fun initializeEffect(duration: Int): Boolean {
        // The effect can't reset if it is running
        // The effect can't initialize with a negative duration
        if (duration <= 0) return false

        resetEffect()
        effectDuration = duration
        effectAnimator =
            ValueAnimator.ofFloat(0f, 1f).apply {
                this.duration = effectDuration.toLong()
                interpolator = AccelerateDecelerateInterpolator()
        // There is no need to re-initialize if the duration has not changed
        if (duration == effectDuration) return true

                doOnStart { handleAnimationStart() }
                addUpdateListener { _effectProgress.value = animatedValue as Float }
                doOnEnd { handleAnimationComplete() }
                doOnCancel { handleAnimationCancel() }
            }
        effectDuration = duration
        longPressHint =
            LongPressHapticBuilder.createLongPressHint(
                durations?.get(0) ?: LongPressHapticBuilder.INVALID_DURATION,
                durations?.get(1) ?: LongPressHapticBuilder.INVALID_DURATION,
                effectDuration
            )
        _postedActionType.value = ActionType.INITIALIZE_ANIMATOR
        setState(State.IDLE)
        return true
    }

@@ -241,5 +206,9 @@ constructor(
        CLICK,
        LONG_PRESS,
        RESET_AND_LONG_PRESS,
        START_ANIMATOR,
        REVERSE_ANIMATOR,
        CANCEL_ANIMATOR,
        INITIALIZE_ANIMATOR,
    }
}
+52 −16

File changed.

Preview size limit exceeded, changes collapsed.