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

Commit 08071338 authored by Ale Nijamkin's avatar Ale Nijamkin Committed by Android (Google) Code Review
Browse files

Merge "[flexiglass] Adds corner "ribbon"." into main

parents 67624f1b fe3ef2de
Loading
Loading
Loading
Loading
+92 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.ribbon.ui.composable

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.layout
import com.android.compose.modifiers.thenIf
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.roundToInt
import kotlin.math.sin
import kotlin.math.tan

/**
 * Renders a "ribbon" at the bottom right corner of its container.
 *
 * The [content] is rendered leaning at an angle of [degrees] degrees (between `1` and `89`,
 * inclusive), with an alpha of [alpha] (between `0f` and `1f`, inclusive).
 *
 * The background color of the strip can be modified by passing a value to the [backgroundColor] or
 * `null` to remove the strip background.
 *
 * Note: this function assumes that it's been placed at the bottom right of its parent by its
 * caller. It's the caller's responsibility to meet that assumption by actually placing this
 * composable element at the bottom right.
 */
@Composable
fun BottomRightCornerRibbon(
    content: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    degrees: Int = 45,
    alpha: Float = 0.6f,
    backgroundColor: Color? = Color.Red,
) {
    check(degrees in 1..89)
    check(alpha in 0f..1f)

    val radians = degrees * (PI / 180)

    Box(
        content = { content() },
        modifier =
            modifier
                .graphicsLayer {
                    this.alpha = alpha

                    val w = size.width
                    val h = size.height

                    val sine = sin(radians).toFloat()
                    val cosine = cos(radians).toFloat()

                    translationX = (w - w * cosine + h * sine) / 2f
                    translationY = (h - w * sine + h * cosine) / 2f
                    rotationZ = 360f - degrees
                }
                .thenIf(backgroundColor != null) { Modifier.background(backgroundColor!!) }
                .layout { measurable, constraints ->
                    val placeable = measurable.measure(constraints)

                    val tangent = tan(radians)
                    val leftPadding = (placeable.measuredHeight / tangent).roundToInt()
                    val rightPadding = (placeable.measuredHeight * tangent).roundToInt()

                    layout(
                        width = placeable.measuredWidth + leftPadding + rightPadding,
                        height = placeable.measuredHeight,
                    ) {
                        placeable.place(leftPadding, 0)
                    }
                }
    )
}
+59 −36
Original line number Diff line number Diff line
@@ -18,14 +18,19 @@

package com.android.systemui.scene.ui.composable

import android.os.SystemProperties
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.motionEventSpy
import androidx.compose.ui.input.pointer.pointerInput
@@ -37,6 +42,7 @@ import com.android.compose.animation.scene.SceneTransitionLayoutState
import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.UserAction as SceneTransitionUserAction
import com.android.compose.animation.scene.observableTransitionState
import com.android.systemui.ribbon.ui.composable.BottomRightCornerRibbon
import com.android.systemui.scene.shared.model.Direction
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
@@ -75,12 +81,16 @@ fun SceneContainer(
    val currentDestinations: Map<UserAction, SceneModel> by
        currentScene.destinationScenes().collectAsState()
    val state = remember { SceneTransitionLayoutState(currentSceneKey.toTransitionSceneKey()) }
    val isRibbonEnabled = remember { SystemProperties.getBoolean("flexi.ribbon", false) }

    DisposableEffect(viewModel, state) {
        viewModel.setTransitionState(state.observableTransitionState().map { it.toModel() })
        onDispose { viewModel.setTransitionState(null) }
    }

    Box(
        modifier = Modifier.fillMaxSize(),
    ) {
        SceneTransitionLayout(
            currentScene = currentSceneKey.toTransitionSceneKey(),
            onChangeScene = viewModel::onSceneChanged,
@@ -123,6 +133,19 @@ fun SceneContainer(
                }
            }
        }

        if (isRibbonEnabled) {
            BottomRightCornerRibbon(
                content = {
                    Text(
                        text = "flexi\uD83E\uDD43",
                        color = Color.White,
                    )
                },
                modifier = Modifier.align(Alignment.BottomEnd),
            )
        }
    }
}

// TODO(b/293899074): remove this once we can use the one from SceneTransitionLayout.