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

Commit fd0e0361 authored by Anton Potapov's avatar Anton Potapov
Browse files

Rework slider touches to support Compose-based implementation

Flag: com.android.systemui.volume_redesign
Bug: 369994956
Test: atest VolumeDialogScreenshotTest
Test: manual on the phone. Check slider adjustements and overscroll
animations

Change-Id: I012cc19b2e8ca223baaf36c88bb03ad10ab2e0a9
parent 5644b9be
Loading
Loading
Loading
Loading
+2 −11
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.systemui.volume.dialog.sliders.domain.interactor

import android.app.ActivityManager
import android.testing.TestableLooper
import android.view.MotionEvent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -29,6 +28,7 @@ import com.android.systemui.testKosmos
import com.android.systemui.volume.Events
import com.android.systemui.volume.dialog.domain.interactor.volumeDialogVisibilityInteractor
import com.android.systemui.volume.dialog.shared.model.VolumeDialogVisibilityModel
import com.android.systemui.volume.dialog.sliders.shared.model.SliderInputEvent
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlin.time.Duration.Companion.seconds
@@ -73,16 +73,7 @@ class VolumeDialogSliderInputEventsInteractorTest : SysuiTestCase() {
                assertThat(dialogVisibility)
                    .isInstanceOf(VolumeDialogVisibilityModel.Visible::class.java)

                underTest.onTouchEvent(
                    MotionEvent.obtain(
                        /* downTime = */ 0,
                        /* eventTime = */ 0,
                        /* action = */ 0,
                        /* x = */ 0f,
                        /* y = */ 0f,
                        /* metaState = */ 0,
                    )
                )
                underTest.onTouchEvent(SliderInputEvent.Touch.Start(0f, 0f))
                advanceTimeBy(volumeDialogTimeout / 2)

                assertThat(dialogVisibility)
+6 −5
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@

package com.android.systemui.volume.dialog.sliders.data.repository

import android.view.MotionEvent
import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
import com.android.systemui.volume.dialog.sliders.shared.model.SliderInputEvent
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -26,10 +26,11 @@ import kotlinx.coroutines.flow.filterNotNull
@VolumeDialogSliderScope
class VolumeDialogSliderTouchEventsRepository @Inject constructor() {

    private val mutableSliderTouchEvents: MutableStateFlow<MotionEvent?> = MutableStateFlow(null)
    val sliderTouchEvent: Flow<MotionEvent> = mutableSliderTouchEvents.filterNotNull()
    private val mutableSliderTouchEvents: MutableStateFlow<SliderInputEvent.Touch?> =
        MutableStateFlow(null)
    val sliderTouchEvent: Flow<SliderInputEvent.Touch> = mutableSliderTouchEvents.filterNotNull()

    fun update(event: MotionEvent) {
        mutableSliderTouchEvents.tryEmit(MotionEvent.obtain(event))
    fun update(touch: SliderInputEvent.Touch) {
        mutableSliderTouchEvents.value = touch
    }
}
+3 −4
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.systemui.volume.dialog.sliders.domain.interactor

import android.view.MotionEvent
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogCallbacksInteractor
import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibilityInteractor
@@ -45,7 +44,7 @@ constructor(

    val event: Flow<SliderInputEvent> =
        merge(
            repository.sliderTouchEvent.map { SliderInputEvent.Touch(it) },
            repository.sliderTouchEvent,
            volumeDialogCallbacksInteractor.event
                .filterIsInstance(VolumeDialogEventModel.VolumeChangedFromKey::class)
                .map { SliderInputEvent.Button },
@@ -55,7 +54,7 @@ constructor(
        event.onEach { visibilityInteractor.resetDismissTimeout() }.launchIn(coroutineScope)
    }

    fun onTouchEvent(newEvent: MotionEvent) {
        repository.update(newEvent)
    fun onTouchEvent(pointerEvent: SliderInputEvent.Touch) {
        repository.update(pointerEvent)
    }
}
+11 −3
Original line number Diff line number Diff line
@@ -16,12 +16,20 @@

package com.android.systemui.volume.dialog.sliders.shared.model

import android.view.MotionEvent

/** Models input event happened on the Volume Slider */
sealed interface SliderInputEvent {

    data class Touch(val event: MotionEvent) : SliderInputEvent
    interface Touch : SliderInputEvent {

        val x: Float
        val y: Float

        data class Start(override val x: Float, override val y: Float) : Touch

        data class Move(override val x: Float, override val y: Float) : Touch

        data class End(override val x: Float, override val y: Float) : Touch
    }

    data object Button : SliderInputEvent
}
+9 −17
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.volume.dialog.sliders.ui

import android.graphics.drawable.Drawable
import android.view.MotionEvent
import android.view.View
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
@@ -44,7 +43,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.PointerEvent
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.unit.dp
@@ -56,15 +54,17 @@ import com.android.systemui.res.R
import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
import com.android.systemui.volume.dialog.sliders.ui.compose.VolumeDialogSliderTrack
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderInputEventsViewModel
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderViewModel
import com.android.systemui.volume.haptics.ui.VolumeHapticsConfigsProvider
import javax.inject.Inject
import kotlin.math.round
import kotlin.math.roundToInt
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.isActive

@VolumeDialogSliderScope
class VolumeDialogSliderViewBinder
@@ -72,7 +72,6 @@ class VolumeDialogSliderViewBinder
constructor(
    private val viewModel: VolumeDialogSliderViewModel,
    private val overscrollViewModel: VolumeDialogOverscrollViewModel,
    private val inputViewModel: VolumeDialogSliderInputEventsViewModel,
    private val hapticsViewModelFactory: SliderHapticsViewModel.Factory,
) {
    fun bind(view: View) {
@@ -80,7 +79,6 @@ constructor(
        sliderComposeView.setContent {
            VolumeDialogSlider(
                viewModel = viewModel,
                inputViewModel = inputViewModel,
                overscrollViewModel = overscrollViewModel,
                hapticsViewModelFactory =
                    if (com.android.systemui.Flags.hapticsForComposeSliders()) {
@@ -97,7 +95,6 @@ constructor(
@Composable
private fun VolumeDialogSlider(
    viewModel: VolumeDialogSliderViewModel,
    inputViewModel: VolumeDialogSliderInputEventsViewModel,
    overscrollViewModel: VolumeDialogOverscrollViewModel,
    hapticsViewModelFactory: SliderHapticsViewModel.Factory?,
    modifier: Modifier = Modifier,
@@ -175,17 +172,12 @@ private fun VolumeDialogSlider(
        interactionSource = interactionSource,
        modifier =
            modifier.pointerInput(Unit) {
                coroutineScope {
                    val currentContext = currentCoroutineContext()
                    awaitPointerEventScope {
                    // we should wait for all new pointer events
                    while (true) {
                        val event: PointerEvent = awaitPointerEvent()
                        PointerEvent::class
                            .java
                            .methods
                            .find { it.name.startsWith("getMotionEvent") }!!
                            .invoke(event)
                            ?.let { it as? MotionEvent? }
                            ?.let { inputViewModel.onTouchEvent(it) }
                        while (currentContext.isActive) {
                            viewModel.onTouchEvent(awaitPointerEvent())
                        }
                    }
                }
            },
Loading