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

Unverified Commit 3775edea authored by Abhay Singh Gill's avatar Abhay Singh Gill Committed by Michael Bestas
Browse files

SystemUI: Allow to change brightness slider positioning in new compose QS



Co-authored-by: default avatarPranav Vashi <neobuddy89@gmail.com>
Change-Id: I57a55c924be7e36d969af4382400e8f0d9415a84
Signed-off-by: default avatarAbhay Singh Gill <abhaygill017@gmail.com>
Signed-off-by: default avatarPranav Vashi <neobuddy89@gmail.com>
parent 2c127225
Loading
Loading
Loading
Loading
+156 −51
Original line number Diff line number Diff line
@@ -19,12 +19,14 @@ package com.android.systemui.qs.composefragment
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.Configuration
import android.database.ContentObserver
import android.graphics.Canvas
import android.graphics.Path
import android.graphics.PointF
import android.graphics.Rect
import android.os.Bundle
import android.os.Trace
import android.os.UserHandle
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
@@ -58,6 +60,7 @@ import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
@@ -99,6 +102,7 @@ import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneTransitionLayout
import com.android.compose.animation.scene.SceneTransitionLayoutState
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.rememberMutableSceneTransitionLayoutState
import com.android.compose.animation.scene.transitions
@@ -177,6 +181,7 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import lineageos.providers.LineageSettings

@SuppressLint("ValidFragment")
class QSFragmentCompose
@@ -740,6 +745,11 @@ constructor(
                        }
                        .padding(top = { qqsPadding }, bottom = { bottomPadding })
            ) {
                val BrightnessSlider: @Composable () -> Unit = {
                    Element(Elements.BrightnessSlider, modifier = modifier) {
                        BrightnessSlider(viewModel, layoutState)
                    }
                }
                val Tiles =
                    @Composable {
                        // When always compose is false, this will always be true, and we'll be
@@ -795,6 +805,7 @@ constructor(
                                .padding(horizontal = qsHorizontalMargin())
                    ) {
                        QuickQuickSettingsLayout(
                            brightness = BrightnessSlider,
                            tiles = Tiles,
                            media = Media,
                            mediaInRow = viewModel.qqsMediaInRow,
@@ -859,36 +870,9 @@ constructor(
                        Spacer(
                            modifier = Modifier.height { qqsPadding + qsExtraPadding.roundToPx() }
                        )
                        val BrightnessSlider =
                            @Composable {
                                Box(
                                    Modifier.systemGestureExclusionInShade(
                                        enabled = {
                                            /*
                                             * While we are transitioning into QS (either from QQS
                                             * or from gone), the global position of the brightness
                                             * slider will change in every frame. This causes
                                             * the modifier to send a new gesture exclusion
                                             * rectangle on every frame. Instead, only apply the
                                             * modifier when this is settled.
                                             */
                                            layoutState.transitionState is TransitionState.Idle &&
                                                viewModel.isNotTransitioning
                                        }
                                    )
                                ) {
                                    AlwaysDarkMode {
                                        BrightnessSliderContainer(
                                            viewModel =
                                                containerViewModel.brightnessSliderViewModel,
                                            containerColors =
                                                ContainerColors(
                                                    Color.Transparent,
                                                    ContainerColors.defaultContainerColor,
                                                ),
                                            modifier = Modifier.fillMaxWidth(),
                                        )
                                    }
                        val BrightnessSlider: @Composable () -> Unit = {
                            Element(Elements.BrightnessSlider, modifier = modifier) {
                                BrightnessSlider(viewModel, layoutState)
                            }
                        }
                        val TileGrid =
@@ -971,6 +955,42 @@ constructor(
        }
    }

    @Composable
    private fun BrightnessSlider(
        viewModel: QSFragmentComposeViewModel,
        layoutState: SceneTransitionLayoutState,
    ) {
        Box(
            Modifier.systemGestureExclusionInShade(
                enabled = {
                    /*
                     * While we are transitioning into QS (either from QQS
                     * or from gone), the global position of the brightness
                     * slider will change in every frame. This causes
                     * the modifier to send a new gesture exclusion
                     * rectangle on every frame. Instead, only apply the
                     * modifier when this is settled.
                     */
                    layoutState.transitionState is TransitionState.Idle &&
                        viewModel.isNotTransitioning
                }
            )
        ) {
            AlwaysDarkMode {
                BrightnessSliderContainer(
                    viewModel =
                        viewModel.containerViewModel.brightnessSliderViewModel,
                    containerColors =
                        ContainerColors(
                            Color.Transparent,
                            ContainerColors.defaultContainerColor,
                        ),
                    modifier = Modifier.fillMaxWidth(),
                )
            }
        }
    }

    @Composable
    private fun EditModeElement(modifier: Modifier = Modifier) {
        // No need for top padding, the Scaffold inside takes care of the correct insets
@@ -1460,10 +1480,20 @@ private fun ContentScope.MediaObject(
@Composable
@VisibleForTesting
fun QuickQuickSettingsLayout(
    brightness: @Composable () -> Unit,
    tiles: @Composable () -> Unit,
    media: @Composable () -> Unit,
    mediaInRow: Boolean,
) {
    val brightnessSettings = rememberQsBrightnessSettings()
    val sliderAtTop = brightnessSettings.sliderAtTop
    val showSlider = brightnessSettings.showSlider

    Column(verticalArrangement = spacedBy(dimensionResource(R.dimen.qs_tile_margin_vertical))) {
        if (showSlider == 2 && sliderAtTop) {
            brightness()
        }

        if (mediaInRow) {
            Row(
                horizontalArrangement = spacedBy(dimensionResource(R.dimen.qs_tile_margin_vertical)),
@@ -1473,8 +1503,14 @@ fun QuickQuickSettingsLayout(
                Box(modifier = Modifier.weight(1f)) { media() }
            }
        } else {
        Column(verticalArrangement = spacedBy(dimensionResource(R.dimen.qs_tile_margin_vertical))) {
            tiles()
        }

        if (showSlider == 2 && !sliderAtTop) {
            brightness()
        }

        if (!mediaInRow) {
            media()
        }
    }
@@ -1489,12 +1525,19 @@ fun QuickSettingsLayout(
    media: @Composable () -> Unit,
    mediaInRow: Boolean,
) {
    if (mediaInRow) {
    val brightnessSettings = rememberQsBrightnessSettings()
    val sliderAtTop = brightnessSettings.sliderAtTop
    val showSlider = brightnessSettings.showSlider

    Column(
            verticalArrangement = spacedBy(QuickSettingsShade.Dimensions.Padding),
            horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = spacedBy(dimensionResource(R.dimen.qs_tile_margin_vertical)),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        if (showSlider != 0 && sliderAtTop) {
            brightness()
        }

        if (mediaInRow) {
            Row(
                horizontalArrangement = spacedBy(QuickSettingsShade.Dimensions.Padding),
                verticalAlignment = Alignment.CenterVertically,
@@ -1502,14 +1545,15 @@ fun QuickSettingsLayout(
                Box(modifier = Modifier.weight(1f)) { tiles() }
                Box(modifier = Modifier.weight(1f)) { media() }
            }
        }
        } else {
        Column(
            verticalArrangement = spacedBy(QuickSettingsShade.Dimensions.Padding),
            horizontalAlignment = Alignment.CenterHorizontally,
        ) {
            brightness()
            tiles()
        }

        if (showSlider != 0 && !sliderAtTop) {
            brightness()
        }

        if (!mediaInRow) {
            media()
        }
    }
@@ -1562,3 +1606,64 @@ private fun AlwaysDarkMode(content: @Composable () -> Unit) {
        }
    }
}

@Composable
private fun rememberQsBrightnessSettings(): QsBrightnessSettings {
    val context = LocalContext.current
    val cr = remember { context.contentResolver }

    fun readCurrent(): QsBrightnessSettings {
        val position = runCatching {
            LineageSettings.Secure.getIntForUser(
                cr, LineageSettings.Secure.QS_BRIGHTNESS_SLIDER_POSITION,
                0, UserHandle.USER_CURRENT
            )
        }.getOrElse { 0 }

        val showSliderValue = runCatching {
            LineageSettings.Secure.getIntForUser(
                cr, LineageSettings.Secure.QS_SHOW_BRIGHTNESS_SLIDER,
                1, UserHandle.USER_CURRENT
            )
        }.getOrElse { 1 }

        return QsBrightnessSettings(
            sliderAtTop = position == 0,
            showSlider = showSliderValue,
        )
    }

    var state by remember {
        mutableStateOf(readCurrent())
    }

    DisposableEffect(Unit) {
        val observer = object : ContentObserver(null) {
            override fun onChange(selfChange: Boolean) {
                context.mainExecutor.execute {
                    state = readCurrent()
                }
            }
        }

        cr.registerContentObserver(
            LineageSettings.Secure.getUriFor(LineageSettings.Secure.QS_BRIGHTNESS_SLIDER_POSITION),
            false, observer, UserHandle.USER_ALL
        )
        cr.registerContentObserver(
            LineageSettings.Secure.getUriFor(LineageSettings.Secure.QS_SHOW_BRIGHTNESS_SLIDER),
            false, observer, UserHandle.USER_ALL
        )

        onDispose {
            cr.unregisterContentObserver(observer)
        }
    }

    return state
}

private data class QsBrightnessSettings(
    val sliderAtTop: Boolean,
    val showSlider: Int,
)
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ fun TransitionBuilder.quickQuickSettingsToQuickSettings(
    anchoredTranslate(Elements.QuickSettingsContent, Elements.GridAnchor)

    sharedElement(Elements.TileElementMatcher, enabled = animateTilesExpansion())
    sharedElement(Elements.BrightnessSlider)

    // This will animate between 0f (QQS) and 0.5, fading in the QQS tiles when coming back
    // from non first page QS. The QS content ends fading out at 0.43f, so there's a brief
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ object QuickSettings {
        val QuickSettingsContent = ElementKey("QuickSettingsContent")
        val GridAnchor = ElementKey("QuickSettingsGridAnchor")
        val FooterActions = ElementKey("QuickSettingsFooterActions")
        val BrightnessSlider = ElementKey("BrightnessSlider")

        fun TileSpec.toElementKey() = ElementKey(this.spec, TileIdentity(this))

+2 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ class QSFragmentComposeTest : SysuiTestCase() {
    fun portraitLayout_qqs() {
        composeTestRule.setContent {
            QuickQuickSettingsLayout(
                brightness = {},
                tiles = { Tiles(TILES_HEIGHT_PORTRAIT) },
                media = { Media() },
                mediaInRow = false,
@@ -70,6 +71,7 @@ class QSFragmentComposeTest : SysuiTestCase() {
    fun landscapeLayout_qqs() {
        composeTestRule.setContent {
            QuickQuickSettingsLayout(
                brightness = {},
                tiles = { Tiles(TILES_HEIGHT_LANDSCAPE) },
                media = { Media() },
                mediaInRow = true,