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

Commit 16ed7a2a authored by Fabián Kozynski's avatar Fabián Kozynski
Browse files

Add a toolbar for dual shade QS actions

This adds a toolbar for dual shade QS containing:
* Edit mode button
* User switcher button
* Settings button
* Power menu button

It leverages the FooterActionsInteractor as well as the individual view
models that FooterActions uses. This means that it uses the same color
tokens. In the future, we'll need to use material color tokens.

It does not include security "footer", as that will be done later.

Test: manual, test buttons in QS shade
Bug: 381279450
Flag: com.android.systemui.dual_shade
Change-Id: I0ef0ecaa76c1058cff443b5e93f71d9edaf0654a
parent 6d15a570
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -261,7 +261,7 @@ private fun RowScope.ForegroundServicesButton(

/** A button with an icon. */
@Composable
private fun IconButton(model: FooterActionsButtonViewModel, modifier: Modifier = Modifier) {
fun IconButton(model: FooterActionsButtonViewModel, modifier: Modifier = Modifier) {
    Expandable(
        color = colorAttr(model.backgroundColor),
        shape = CircleShape,
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import com.android.systemui.qs.flags.QsDetailedView
import com.android.systemui.qs.panels.ui.compose.EditMode
import com.android.systemui.qs.panels.ui.compose.TileDetails
import com.android.systemui.qs.panels.ui.compose.TileGrid
import com.android.systemui.qs.panels.ui.compose.toolbar.Toolbar
import com.android.systemui.qs.ui.composable.QuickSettingsShade.Dimensions.GridMaxHeight
import com.android.systemui.qs.ui.viewmodel.QuickSettingsContainerViewModel
import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeOverlayActionsViewModel
@@ -189,6 +190,7 @@ fun SceneScope.QuickSettingsLayout(
                    bottom = QuickSettingsShade.Dimensions.Padding / 2,
                ),
    ) {
        Toolbar(viewModel.toolbarViewModelFactory)
        BrightnessSliderContainer(
            viewModel = viewModel.brightnessSliderViewModel,
            modifier =
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import com.android.systemui.classifier.fakeFalsingManager
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.qs.panels.ui.viewmodel.toolbar.editModeButtonViewModelFactory
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import org.junit.Test
+9 −0
Original line number Diff line number Diff line
@@ -74,3 +74,12 @@ constructor(
    /** Returns `true` if the tap gesture should be rejected */
    fun isFalseTap(@Penalty penalty: Int): Boolean = manager.isFalseTap(penalty)
}

inline fun FalsingInteractor.runIfNotFalseTap(
    penalty: Int = FalsingManager.LOW_PENALTY,
    action: () -> Unit,
) {
    if (!isFalseTap(penalty)) {
        action()
    }
}
+41 −37
Original line number Diff line number Diff line
@@ -23,12 +23,12 @@ import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.LifecycleOwner
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.settingslib.Utils
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.globalactions.GlobalActionsDialogLite
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
@@ -38,6 +38,7 @@ import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.util.icuMessageFormat
import javax.inject.Inject
import javax.inject.Named
@@ -54,7 +55,6 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.isActive
import com.android.app.tracing.coroutines.launchTraced as launch

private const val TAG = "FooterActionsViewModel"

@@ -211,7 +211,7 @@ fun FooterActionsViewModel(
                false /* if the dismiss should be deferred */
            },
            null /* cancelAction */,
            true /* afterKeyguardGone */
            true, /* afterKeyguardGone */
        )
    }

@@ -269,7 +269,32 @@ fun FooterActionsViewModel(
            .distinctUntilChanged()

    val userSwitcher =
        footerActionsInteractor.userSwitcherStatus
        userSwitcherViewModel(qsThemedContext, footerActionsInteractor, ::onUserSwitcherClicked)

    val settings = settingsButtonViewModel(qsThemedContext, ::onSettingsButtonClicked)
    val power =
        if (showPowerButton) {
            powerButtonViewModel(qsThemedContext, ::onPowerButtonClicked)
        } else {
            null
        }

    return FooterActionsViewModel(
        security = security,
        foregroundServices = foregroundServices,
        userSwitcher = userSwitcher,
        settings = settings,
        power = power,
        observeDeviceMonitoringDialogRequests = ::observeDeviceMonitoringDialogRequests,
    )
}

fun userSwitcherViewModel(
    themedContext: Context,
    footerActionsInteractor: FooterActionsInteractor,
    onUserSwitcherClicked: (Expandable) -> Unit,
): Flow<FooterActionsButtonViewModel?> {
    return footerActionsInteractor.userSwitcherStatus
        .map { userSwitcherStatus ->
            when (userSwitcherStatus) {
                UserSwitcherStatusModel.Disabled -> null
@@ -284,31 +309,14 @@ fun FooterActionsViewModel(
                    }

                    userSwitcherButtonViewModel(
                            qsThemedContext,
                        themedContext,
                        userSwitcherStatus,
                            ::onUserSwitcherClicked
                        onUserSwitcherClicked,
                    )
                }
            }
        }
        .distinctUntilChanged()

    val settings = settingsButtonViewModel(qsThemedContext, ::onSettingsButtonClicked)
    val power =
        if (showPowerButton) {
            powerButtonViewModel(qsThemedContext, ::onPowerButtonClicked)
        } else {
            null
        }

    return FooterActionsViewModel(
        security = security,
        foregroundServices = foregroundServices,
        userSwitcher = userSwitcher,
        settings = settings,
        power = power,
        observeDeviceMonitoringDialogRequests = ::observeDeviceMonitoringDialogRequests,
    )
}

fun securityButtonViewModel(
@@ -369,7 +377,7 @@ fun userSwitcherButtonViewModel(

private fun userSwitcherContentDescription(
    qsThemedContext: Context,
    currentUser: String?
    currentUser: String?,
): String? {
    return currentUser?.let { user ->
        qsThemedContext.getString(R.string.accessibility_quick_settings_user, user)
@@ -384,13 +392,9 @@ fun settingsButtonViewModel(
        id = R.id.settings_button_container,
        Icon.Resource(
            R.drawable.ic_settings,
            ContentDescription.Resource(R.string.accessibility_quick_settings_settings)
        ),
        iconTint =
            Utils.getColorAttrDefaultColor(
                qsThemedContext,
                R.attr.onShadeInactiveVariant,
            ContentDescription.Resource(R.string.accessibility_quick_settings_settings),
        ),
        iconTint = Utils.getColorAttrDefaultColor(qsThemedContext, R.attr.onShadeInactiveVariant),
        backgroundColor = R.attr.shadeInactive,
        onSettingsButtonClicked,
    )
@@ -404,14 +408,14 @@ fun powerButtonViewModel(
        id = R.id.pm_lite,
        Icon.Resource(
            android.R.drawable.ic_lock_power_off,
            ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu)
            ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu),
        ),
        iconTint =
            Utils.getColorAttrDefaultColor(
                qsThemedContext,
                R.attr.onShadeActive,
                if (DualShade.isEnabled) R.attr.onShadeInactiveVariant else R.attr.onShadeActive,
            ),
        backgroundColor = R.attr.shadeActive,
        backgroundColor = if (DualShade.isEnabled) R.attr.shadeInactive else R.attr.shadeActive,
        onPowerButtonClicked,
    )
}
Loading