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

Commit 408e0d82 authored by Bharat Singh's avatar Bharat Singh
Browse files

[SysUI][Floaty] Move to Animatable to ensure window destruction

Due to custom delays in squeeze animation, animateFloatAsState's
finishedListener is not super handy to invoke effect window's
destruction. This CL moves the animation logic to use Animatable
to handle custom delays as well as destruction of effects window.

Bug: 399263897
Flag: com.android.systemui.shared.enable_lpp_assist_invocation_effect
Change-Id: I65a60d4734fc5ed952957a71150ab49493728035
parent caa42f85
Loading
Loading
Loading
Loading
+56 −13
Original line number Diff line number Diff line
@@ -16,12 +16,16 @@

package com.android.systemui.topwindoweffects.ui.compose

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
@@ -48,29 +52,68 @@ fun SqueezeEffect(
    modifier: Modifier = Modifier
) {
    val viewModel = rememberViewModel(traceName = "SqueezeEffect") { viewModelFactory.create() }

    val down = viewModel.isPowerButtonPressed
    val longPressed = viewModel.isPowerButtonLongPressed

    // TODO: Choose the correct resource based on primary / secondary display
    val top = rememberVectorPainter(ImageVector.vectorResource(R.drawable.rounded_corner_top))
    val bottom = rememberVectorPainter(ImageVector.vectorResource(R.drawable.rounded_corner_bottom))

    val squeezeProgress by animateFloatAsState(
        targetValue =
            if (down && !longPressed) {
                1f
    val squeezeProgress = remember { Animatable(0f) }

    // Flag to check if the squeeze effect is interruptible or not. If the power button was long
    // pressed, the squeeze animation finishes without being interrupted by the state of power
    // button.
    var isSqueezeAnimationInterruptible by remember { mutableStateOf(true) }

    // Flag to check if Squeeze effect progressing inward on the device (progress value moving
    // towards 1). There are following possible cases for squeeze effect animation -
    // Case 1 - Power button was long pressed
    //      Squeeze effect progress value goes to 1 and afterwards this value goes back to 0.
    // Case 2 - Power button was pressed but released just before long press threshold
    //      Squeeze effect progress value goes towards 1 and as soon as the power button is released
    //      this value goes back to 0.
    // In both the above cases, as soon as the squeeze effect finishes animating (progress value
    // becomes 0 again), we execute the "onEffectFinished" block which ensures that effects window
    // is removed.
    var isSqueezeEffectAnimatingInwards by remember { mutableStateOf(false) }

    LaunchedEffect(longPressed) {
        if (longPressed) {
            isSqueezeAnimationInterruptible = false
        }
    }

    LaunchedEffect(down, isSqueezeAnimationInterruptible) {
        isSqueezeEffectAnimatingInwards = down || !isSqueezeAnimationInterruptible
    }

    LaunchedEffect(isSqueezeEffectAnimatingInwards) {
        if (isSqueezeEffectAnimatingInwards) {
            squeezeProgress.animateTo(1f, animationSpec = tween(durationMillis = 800))
            squeezeProgress.animateTo(0f, animationSpec = tween(durationMillis = 333))
            if (squeezeProgress.value == 0f) {
                onEffectFinished()
            }
            isSqueezeAnimationInterruptible = true
        } else {
                0f
            },
        animationSpec = tween(durationMillis = 400),
        finishedListener = { onEffectFinished() }
    )
            if (squeezeProgress.value != 0f) {
                squeezeProgress
                    .animateTo(0f, animationSpec = tween(durationMillis = 333))
            }
            if (squeezeProgress.value == 0f) {
                onEffectFinished()
            }
        }
    }

    Canvas(modifier = modifier.fillMaxSize()) {
        if (squeezeProgress <= 0) {
        if (squeezeProgress.value <= 0) {
            return@Canvas
        }

        val squeezeThickness = SqueezeEffectMaxThickness.toPx() * squeezeProgress
        val squeezeThickness = SqueezeEffectMaxThickness.toPx() * squeezeProgress.value

        drawRect(color = SqueezeColor, size = Size(size.width, squeezeThickness))

+0 −2
Original line number Diff line number Diff line
@@ -32,13 +32,11 @@ constructor(

    val isPowerButtonPressed: Boolean by hydrator.hydratedStateOf(
        traceName = "isPowerButtonPressed",
        initialValue = false,
        source = keyEventInteractor.isPowerButtonDown
    )

    val isPowerButtonLongPressed: Boolean by hydrator.hydratedStateOf(
        traceName = "isPowerButtonLongPressed",
        initialValue = false,
        source = keyEventInteractor.isPowerButtonLongPressed
    )