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

Commit 532e378b authored by burakov's avatar burakov
Browse files

[bc25] Add initial Quick Settings rendering in QuickSettingsShadeScene.

Test: Manually tested by opening and closing the quick settings shade on
a foldable device both in a folded and unfolded configuration.
Test: Unit tests build and pass.
Bug: 344008947
Flag: com.android.systemui.dual_shade

Change-Id: If7126eac51f4636616556f231eb2e64b377445d7
parent f6fea76f
Loading
Loading
Loading
Loading
+84 −9
Original line number Diff line number Diff line
@@ -16,22 +16,38 @@

package com.android.systemui.qs.ui.composable

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.brightness.ui.compose.BrightnessSliderContainer
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.ui.composable.LockscreenContent
import com.android.systemui.qs.panels.ui.compose.EditMode
import com.android.systemui.qs.panels.ui.compose.TileGrid
import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneViewModel
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.ComposableScene
import com.android.systemui.shade.ui.composable.OverlayShade
import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel
import dagger.Lazy
import java.util.Optional
import javax.inject.Inject
@@ -41,8 +57,7 @@ import kotlinx.coroutines.flow.StateFlow
class QuickSettingsShadeScene
@Inject
constructor(
    viewModel: QuickSettingsShadeSceneViewModel,
    private val overlayShadeViewModel: OverlayShadeViewModel,
    private val viewModel: QuickSettingsShadeSceneViewModel,
    private val lockscreenContent: Lazy<Optional<LockscreenContent>>,
) : ComposableScene {

@@ -56,21 +71,81 @@ constructor(
        modifier: Modifier,
    ) {
        OverlayShade(
            viewModel = overlayShadeViewModel,
            modifier = modifier,
            viewModel = viewModel.overlayShadeViewModel,
            horizontalArrangement = Arrangement.End,
            lockscreenContent = lockscreenContent,
            modifier = modifier,
        ) {
            val isEditing by viewModel.editModeViewModel.isEditing.collectAsStateWithLifecycle()

            // The main Quick Settings grid layout.
            AnimatedVisibility(
                visible = !isEditing,
                enter = QuickSettingsShade.Transitions.QuickSettingsLayoutEnter,
                exit = QuickSettingsShade.Transitions.QuickSettingsLayoutExit,
            ) {
                QuickSettingsLayout(
                    viewModel = viewModel,
                )
            }

            // The Quick Settings Editor layout.
            AnimatedVisibility(
                visible = isEditing,
                enter = QuickSettingsShade.Transitions.QuickSettingsEditorEnter,
                exit = QuickSettingsShade.Transitions.QuickSettingsEditorExit,
            ) {
                EditMode(
                    viewModel = viewModel.editModeViewModel,
                    modifier =
                        Modifier.fillMaxWidth().padding(QuickSettingsShade.Dimensions.Padding)
                )
            }
        }
    }
}

@Composable
private fun QuickSettingsLayout(
    viewModel: QuickSettingsShadeSceneViewModel,
    modifier: Modifier = Modifier,
) {
            Text(
                text = "Quick settings grid",
                modifier = Modifier.padding(QuickSettingsShade.Dimensions.Padding)
    Column(
        verticalArrangement = Arrangement.spacedBy(QuickSettingsShade.Dimensions.Padding),
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = modifier.fillMaxWidth().padding(QuickSettingsShade.Dimensions.Padding),
    ) {
        BrightnessSliderContainer(
            viewModel = viewModel.brightnessSliderViewModel,
            modifier =
                Modifier.fillMaxWidth()
                    .height(QuickSettingsShade.Dimensions.BrightnessSliderHeight),
        )
        TileGrid(
            viewModel = viewModel.tileGridViewModel,
            modifier =
                Modifier.fillMaxWidth().heightIn(max = QuickSettingsShade.Dimensions.GridMaxHeight),
        )
        Button(
            onClick = { viewModel.editModeViewModel.startEditing() },
        ) {
            Text("Edit mode")
        }
    }
}

object QuickSettingsShade {

    object Dimensions {
        val Padding = 16.dp
        val BrightnessSliderHeight = 64.dp
        val GridMaxHeight = 400.dp
    }

    object Transitions {
        val QuickSettingsLayoutEnter: EnterTransition = fadeIn(tween(500))
        val QuickSettingsLayoutExit: ExitTransition = fadeOut(tween(500))
        val QuickSettingsEditorEnter: EnterTransition = fadeIn(tween(500))
        val QuickSettingsEditorExit: ExitTransition = fadeOut(tween(500))
    }
}
+6 −6
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
    private AutoTileManager mAutoTiles;
    private final ArrayList<QSFactory> mQsFactories = new ArrayList<>();
    private int mCurrentUser;
    private final ShadeController mShadeController;
    private final Lazy<ShadeController> mShadeControllerProvider;
    private Context mUserContext;
    private UserTracker mUserTracker;
    private SecureSettings mSecureSettings;
@@ -130,7 +130,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
            PluginManager pluginManager,
            TunerService tunerService,
            Provider<AutoTileManager> autoTiles,
            ShadeController shadeController,
            Lazy<ShadeController> shadeControllerProvider,
            QSLogger qsLogger,
            UserTracker userTracker,
            SecureSettings secureSettings,
@@ -149,7 +149,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
        mUserFileManager = userFileManager;
        mFeatureFlags = featureFlags;

        mShadeController = shadeController;
        mShadeControllerProvider = shadeControllerProvider;

        if (featureFlags.getTilesEnabled()) {
            mQsFactories.add(newQsTileFactoryProvider.get());
@@ -216,17 +216,17 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P

    @Override
    public void collapsePanels() {
        mShadeController.postAnimateCollapseShade();
        mShadeControllerProvider.get().postAnimateCollapseShade();
    }

    @Override
    public void forceCollapsePanels() {
        mShadeController.postAnimateForceCollapseShade();
        mShadeControllerProvider.get().postAnimateForceCollapseShade();
    }

    @Override
    public void openPanels() {
        mShadeController.postAnimateExpandQs();
        mShadeControllerProvider.get().postAnimateExpandQs();
    }

    @Override
+9 −1
Original line number Diff line number Diff line
@@ -21,8 +21,12 @@ import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.brightness.ui.viewmodel.BrightnessSliderViewModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.qs.panels.ui.viewmodel.EditModeViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel
import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -37,7 +41,11 @@ class QuickSettingsShadeSceneViewModel
@Inject
constructor(
    @Application private val applicationScope: CoroutineScope,
    overlayShadeViewModel: OverlayShadeViewModel,
    val overlayShadeViewModel: OverlayShadeViewModel,
    val brightnessSliderViewModel: BrightnessSliderViewModel,
    val tileGridViewModel: TileGridViewModel,
    val editModeViewModel: EditModeViewModel,
    val qsSceneAdapter: QSSceneAdapter,
) {
    val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
        overlayShadeViewModel.backgroundScene
+2 −6
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.Expandable;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.nano.SystemUIProtoDump;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.qs.QSFactory;
@@ -133,8 +132,6 @@ public class QSTileHostTest extends SysuiTestCase {

    private SparseArray<SharedPreferences> mSharedPreferencesByUser;

    private FakeFeatureFlags mFeatureFlags;

    private QSPipelineFlagsRepository mQSPipelineFlagsRepository;

    private FakeExecutor mMainExecutor;
@@ -144,7 +141,6 @@ public class QSTileHostTest extends SysuiTestCase {
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mFeatureFlags = new FakeFeatureFlags();

        mSetFlagsRule.disableFlags(FLAG_QS_NEW_PIPELINE);
        mSetFlagsRule.disableFlags(FLAG_QS_NEW_TILES);
@@ -170,7 +166,7 @@ public class QSTileHostTest extends SysuiTestCase {
        saveSetting("");
        setUpTileFactory();
        mQSTileHost = new TestQSTileHost(mContext, () -> null, mDefaultFactory, mMainExecutor,
                mPluginManager, mTunerService, () -> mAutoTiles, mShadeController,
                mPluginManager, mTunerService, () -> mAutoTiles, () -> mShadeController,
                mQSLogger, mUserTracker, mSecureSettings, mCustomTileStatePersister,
                mTileLifecycleManagerFactory, mUserFileManager, mQSPipelineFlagsRepository);
        mMainExecutor.runAllReady();
@@ -689,7 +685,7 @@ public class QSTileHostTest extends SysuiTestCase {
                QSFactory defaultFactory, Executor mainExecutor,
                PluginManager pluginManager, TunerService tunerService,
                Provider<AutoTileManager> autoTiles,
                ShadeController shadeController, QSLogger qsLogger,
                Lazy<ShadeController> shadeController, QSLogger qsLogger,
                UserTracker userTracker, SecureSettings secureSettings,
                CustomTileStatePersister customTileStatePersister,
                TileLifecycleManager.Factory tileLifecycleManagerFactory,
+31 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.brightness.ui.viewmodel

import com.android.systemui.brightness.domain.interactor.brightnessPolicyEnforcementInteractor
import com.android.systemui.brightness.domain.interactor.screenBrightnessInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope

val Kosmos.brightnessSliderViewModel: BrightnessSliderViewModel by
    Kosmos.Fixture {
        BrightnessSliderViewModel(
            screenBrightnessInteractor = screenBrightnessInteractor,
            brightnessPolicyEnforcementInteractor = brightnessPolicyEnforcementInteractor,
            applicationScope = applicationCoroutineScope,
        )
    }
Loading