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

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

Merge "Fix Volume Dialog dismiss on touch outside" into main

parents ea743832 0682386d
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import com.android.systemui.volume.dialog.ringer.ui.viewmodel.RingerViewModel
import com.android.systemui.volume.dialog.ringer.ui.viewmodel.RingerViewModelState
import com.android.systemui.volume.dialog.ringer.ui.viewmodel.VolumeDialogRingerDrawerViewModel
import com.android.systemui.volume.dialog.ui.utils.suspendAnimate
import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogViewModel
import javax.inject.Inject
import kotlin.properties.Delegates
import kotlinx.coroutines.CoroutineScope
@@ -56,7 +57,10 @@ private const val BUTTON_MIN_VISIBLE_CHANGE = 0.05F
@VolumeDialogScope
class VolumeDialogRingerViewBinder
@Inject
constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) {
constructor(
    private val viewModel: VolumeDialogRingerDrawerViewModel,
    private val dialogViewModel: VolumeDialogViewModel,
) {
    private val roundnessSpringForce =
        SpringForce(1F).apply {
            stiffness = 800F
@@ -116,6 +120,7 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) {
        drawerContainer.setTransitionListener(ringerDrawerTransitionListener)
        volumeDialogBackgroundView.background = volumeDialogBackgroundView.background.mutate()
        ringerBackgroundView.background = ringerBackgroundView.background.mutate()
        launch { dialogViewModel.addTouchableBounds(drawerContainer) }

        viewModel.ringerViewModel
            .mapLatest { ringerState ->
+7 −1
Original line number Diff line number Diff line
@@ -21,18 +21,24 @@ import android.widget.ImageButton
import com.android.systemui.res.R
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
import com.android.systemui.volume.dialog.settings.ui.viewmodel.VolumeDialogSettingsButtonViewModel
import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogViewModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch

@VolumeDialogScope
class VolumeDialogSettingsButtonViewBinder
@Inject
constructor(private val viewModel: VolumeDialogSettingsButtonViewModel) {
constructor(
    private val viewModel: VolumeDialogSettingsButtonViewModel,
    private val dialogViewModel: VolumeDialogViewModel,
) {

    fun CoroutineScope.bind(view: View) {
        val button = view.requireViewById<ImageButton>(R.id.volume_dialog_settings)
        launch { dialogViewModel.addTouchableBounds(button) }
        viewModel.isVisible
            .onEach { isVisible -> button.visibility = if (isVisible) View.VISIBLE else View.GONE }
            .launchIn(this)
+7 −1
Original line number Diff line number Diff line
@@ -25,15 +25,20 @@ import com.android.systemui.res.R
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderComponent
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSlidersViewModel
import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogViewModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch

@VolumeDialogScope
class VolumeDialogSlidersViewBinder
@Inject
constructor(private val viewModel: VolumeDialogSlidersViewModel) {
constructor(
    private val viewModel: VolumeDialogSlidersViewModel,
    private val dialogViewModel: VolumeDialogViewModel,
) {

    fun CoroutineScope.bind(view: View) {
        val floatingSlidersContainer: ViewGroup =
@@ -44,6 +49,7 @@ constructor(private val viewModel: VolumeDialogSlidersViewModel) {
        val settingsButton: View = view.requireViewById(R.id.volume_dialog_settings)
        val ringerDrawer: View = view.requireViewById(R.id.volume_ringer_drawer)

        launch { dialogViewModel.addTouchableBounds(mainSliderContainer, floatingSlidersContainer) }
        viewModel.sliders
            .onEach { uiModel ->
                bindSlider(
+5 −20
Original line number Diff line number Diff line
@@ -18,12 +18,8 @@ package com.android.systemui.volume.dialog.ui.binder

import android.app.Dialog
import android.content.res.Resources
import android.graphics.Rect
import android.graphics.Region
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.ViewTreeObserver.InternalInsetsInfo
import android.view.WindowInsets
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.core.view.updatePadding
@@ -31,7 +27,6 @@ import com.android.internal.view.RotationPolicy
import com.android.systemui.common.ui.view.onApplyWindowInsets
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
import com.android.systemui.util.children
import com.android.systemui.util.kotlin.awaitCancellationThenDispose
import com.android.systemui.volume.SystemUIInterpolators
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
@@ -45,6 +40,7 @@ import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogViewModel
import com.android.systemui.volume.dialog.utils.VolumeTracer
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
@@ -55,6 +51,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine

/** Binds the root view of the Volume Dialog. */
@OptIn(ExperimentalCoroutinesApi::class)
@VolumeDialogScope
class VolumeDialogViewBinder
@Inject
@@ -90,7 +87,7 @@ constructor(
            }
            .launchIn(this)

        launch { root.viewTreeObserver.computeInternalInsetsListener(root) }
        launch { root.viewTreeObserver.listenToComputeInternalInsets() }

        launch {
            root
@@ -177,28 +174,16 @@ constructor(
        animator.suspendAnimate(jankListenerFactory.dismiss(this, duration))
    }

    private suspend fun ViewTreeObserver.computeInternalInsetsListener(viewGroup: ViewGroup) =
    private suspend fun ViewTreeObserver.listenToComputeInternalInsets() =
        suspendCancellableCoroutine<Unit> { continuation ->
            val listener =
                ViewTreeObserver.OnComputeInternalInsetsListener { inoutInfo ->
                    viewGroup.fillTouchableBounds(inoutInfo)
                    viewModel.fillTouchableBounds(inoutInfo)
                }
            addOnComputeInternalInsetsListener(listener)
            continuation.invokeOnCancellation { removeOnComputeInternalInsetsListener(listener) }
        }

    private fun ViewGroup.fillTouchableBounds(internalInsetsInfo: InternalInsetsInfo) {
        for (child in children) {
            val boundsRect = Rect()
            internalInsetsInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION)

            child.getBoundsInWindow(boundsRect, false)
            internalInsetsInfo.touchableRegion.op(boundsRect, Region.Op.UNION)
        }
        val boundsRect = Rect()
        getBoundsInWindow(boundsRect, false)
    }

    private fun MotionLayout.transitionToState(newState: Int, animate: Boolean) {
        if (animate) {
            transitionToState(newState)
+22 −0
Original line number Diff line number Diff line
@@ -18,6 +18,10 @@ package com.android.systemui.volume.dialog.ui.viewmodel

import android.content.Context
import android.content.res.Configuration
import android.graphics.Rect
import android.graphics.Region
import android.view.View
import android.view.ViewTreeObserver.InternalInsetsInfo
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.DevicePostureController
@@ -37,6 +41,7 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.suspendCancellableCoroutine

/** Provides a state for the Volume Dialog. */
@VolumeDialogScope
@@ -77,10 +82,27 @@ constructor(
            }
            .filterNotNull()

    private val touchableBoundsViews: MutableCollection<View> = mutableSetOf()

    /** @return true when the foldable device screen curve is in the way of the volume dialog */
    private fun shouldOffsetVolumeDialog(devicePosture: Int, config: Configuration): Boolean {
        val isLandscape = config.orientation == Configuration.ORIENTATION_LANDSCAPE
        val isHalfOpen = devicePosture == DevicePostureController.DEVICE_POSTURE_HALF_OPENED
        return isLandscape && isHalfOpen
    }

    fun fillTouchableBounds(internalInsetsInfo: InternalInsetsInfo) {
        for (child in touchableBoundsViews) {
            val boundsRect = Rect()
            internalInsetsInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION)

            child.getBoundsInWindow(boundsRect, false)
            internalInsetsInfo.touchableRegion.op(boundsRect, Region.Op.UNION)
        }
    }

    suspend fun addTouchableBounds(vararg views: View): Nothing = suspendCancellableCoroutine {
        touchableBoundsViews.addAll(views)
        it.invokeOnCancellation { touchableBoundsViews.removeAll(views.toSet()) }
    }
}
Loading