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

Commit d0e1453a authored by Olivier St-Onge's avatar Olivier St-Onge Committed by Android (Google) Code Review
Browse files

Merge "Adjust colors for QS footer buttons" into main

parents b94db066 793e16dc
Loading
Loading
Loading
Loading
+122 −17
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
@@ -46,6 +45,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -75,6 +75,7 @@ import androidx.lifecycle.repeatOnLifecycle
import com.android.compose.animation.Expandable
import com.android.compose.animation.scene.ContentScope
import com.android.compose.modifiers.animatedBackground
import com.android.compose.theme.LocalAndroidColorScheme
import com.android.compose.theme.colorAttr
import com.android.systemui.Flags.notificationShadeBlur
import com.android.systemui.animation.Expandable
@@ -337,8 +338,9 @@ fun IconButton(
    useModifierBasedExpandable: Boolean,
    modifier: Modifier = Modifier,
) {
    val colors = buttonColorsForModel(model)
    Expandable(
        color = colorAttr(model.backgroundColor),
        color = colors.background,
        shape = CircleShape,
        onClick = model.onClick,
        modifier =
@@ -348,8 +350,7 @@ fun IconButton(
            ),
        useModifierBasedImplementation = useModifierBasedExpandable,
    ) {
        val tint = model.iconTint?.let { Color(it) } ?: Color.Unspecified
        Icon(model.icon, tint = tint, modifier = Modifier.size(20.dp))
        Icon(model.icon, tint = colors.icon, modifier = Modifier.size(20.dp))
    }
}

@@ -370,8 +371,9 @@ private fun NumberButton(
    // dot".
    val interactionSource = remember { MutableInteractionSource() }

    val colors = numberButtonColors()
    Expandable(
        color = colorAttr(R.attr.shadeInactive),
        color = colors.background,
        shape = CircleShape,
        onClick = onClick,
        interactionSource = interactionSource,
@@ -395,7 +397,7 @@ private fun NumberButton(
                            this.contentDescription = contentDescription
                        },
                    style = MaterialTheme.typography.bodyLarge,
                    color = colorAttr(R.attr.onShadeInactiveVariant),
                    color = colors.content,
                    // TODO(b/242040009): This should only use a standard text style instead and
                    // should not override the text size.
                    fontSize = 18.sp,
@@ -421,7 +423,6 @@ private fun NewChangesDot(modifier: Modifier = Modifier) {
}

/** A larger button with an icon, some text and an optional dot (to indicate new changes). */
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
private fun TextButton(
    icon: Icon,
@@ -431,11 +432,12 @@ private fun TextButton(
    useModifierBasedExpandable: Boolean,
    modifier: Modifier = Modifier,
) {
    val colors = textButtonColors()
    Expandable(
        shape = CircleShape,
        color = colorAttr(R.attr.underSurface),
        contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
        borderStroke = BorderStroke(1.dp, colorAttr(R.attr.shadeInactive)),
        color = colors.background,
        contentColor = colors.content,
        borderStroke = colors.border,
        modifier =
            modifier
                .padding(horizontal = 4.dp)
@@ -447,11 +449,7 @@ private fun TextButton(
            Modifier.padding(horizontal = dimensionResource(R.dimen.qs_footer_padding)),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Icon(
                icon,
                Modifier.padding(end = 12.dp).size(20.dp),
                colorAttr(R.attr.onShadeInactiveVariant),
            )
            Icon(icon, Modifier.padding(end = 12.dp).size(20.dp), colors.content)

            Text(
                text,
@@ -463,7 +461,7 @@ private fun TextButton(
                        MaterialTheme.typography.bodyMedium
                    },
                letterSpacing = if (QsInCompose.isEnabled) 0.em else 0.01.em,
                color = colorAttr(R.attr.onShadeInactiveVariant),
                color = colors.content,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
            )
@@ -477,9 +475,116 @@ private fun TextButton(
                    painterResource(com.android.internal.R.drawable.ic_chevron_end),
                    contentDescription = null,
                    Modifier.padding(start = 8.dp).size(20.dp),
                    colorAttr(R.attr.onShadeInactiveVariant),
                    colors.content,
                )
            }
        }
    }
}

@Composable
@ReadOnlyComposable
private fun textButtonColors(): TextButtonColors {
    return if (QsInCompose.isEnabled && notificationShadeBlur()) {
        FooterActionsDefaults.blurTextButtonColors()
    } else {
        FooterActionsDefaults.textButtonColors()
    }
}

@Composable
@ReadOnlyComposable
private fun numberButtonColors(): TextButtonColors {
    return if (QsInCompose.isEnabled && notificationShadeBlur()) {
        FooterActionsDefaults.blurTextButtonColors()
    } else {
        FooterActionsDefaults.numberButtonColors()
    }
}

@Composable
@ReadOnlyComposable
private fun buttonColorsForModel(footerAction: FooterActionsButtonViewModel): ButtonColors {
    return if (QsInCompose.isEnabled && notificationShadeBlur()) {
        when (footerAction) {
            is FooterActionsButtonViewModel.PowerActionViewModel -> {
                if (footerAction.isOnDualShade) {
                    FooterActionsDefaults.inactiveButtonColors()
                } else {
                    FooterActionsDefaults.activeButtonColors()
                }
            }
            is FooterActionsButtonViewModel.SettingsActionViewModel ->
                FooterActionsDefaults.inactiveButtonColors()
            is FooterActionsButtonViewModel.UserSwitcherViewModel ->
                FooterActionsDefaults.userSwitcherButtonColors()
        }
    } else {
        ButtonColors(
            icon = footerAction.iconTintFallback?.let { Color(it) } ?: Color.Unspecified,
            background = colorAttr(footerAction.backgroundColorFallback),
        )
    }
}

private data class ButtonColors(val icon: Color, val background: Color)

private data class TextButtonColors(
    val content: Color,
    val background: Color,
    val border: BorderStroke?,
)

private object FooterActionsDefaults {

    @Composable
    @ReadOnlyComposable
    fun activeButtonColors(): ButtonColors =
        ButtonColors(
            icon = MaterialTheme.colorScheme.onPrimary,
            background = MaterialTheme.colorScheme.primary,
        )

    @Composable
    @ReadOnlyComposable
    fun inactiveButtonColors(): ButtonColors =
        ButtonColors(
            icon = MaterialTheme.colorScheme.onSurface,
            background = LocalAndroidColorScheme.current.surfaceEffect2,
        )

    @Composable
    @ReadOnlyComposable
    fun userSwitcherButtonColors(): ButtonColors =
        ButtonColors(
            icon = Color.Unspecified,
            background = LocalAndroidColorScheme.current.surfaceEffect2,
        )

    @Composable
    @ReadOnlyComposable
    fun blurTextButtonColors(): TextButtonColors =
        TextButtonColors(
            content = MaterialTheme.colorScheme.onSurface,
            background = LocalAndroidColorScheme.current.surfaceEffect2,
            border = null,
        )

    @Composable
    @ReadOnlyComposable
    fun textButtonColors(): TextButtonColors =
        TextButtonColors(
            content = colorAttr(R.attr.onShadeInactiveVariant),
            background = colorAttr(R.attr.underSurface),
            border = BorderStroke(1.dp, colorAttr(R.attr.shadeInactive)),
        )

    @Composable
    @ReadOnlyComposable
    fun numberButtonColors(): TextButtonColors =
        TextButtonColors(
            content = colorAttr(R.attr.onShadeInactiveVariant),
            background = colorAttr(R.attr.shadeInactive),
            border = null,
        )
}
+6 −6
Original line number Diff line number Diff line
@@ -111,8 +111,8 @@ class FooterActionsViewModelTest : SysuiTestCase() {
                    ContentDescription.Resource(R.string.accessibility_quick_settings_settings),
                )
            )
        assertThat(settings.backgroundColor).isEqualTo(R.attr.shadeInactive)
        assertThat(settings.iconTint)
        assertThat(settings.backgroundColorFallback).isEqualTo(R.attr.shadeInactive)
        assertThat(settings.iconTintFallback)
            .isEqualTo(Utils.getColorAttrDefaultColor(themedContext, R.attr.onShadeInactiveVariant))
    }

@@ -136,8 +136,8 @@ class FooterActionsViewModelTest : SysuiTestCase() {
                    ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu),
                )
            )
        assertThat(checkNotNull(power).backgroundColor).isEqualTo(R.attr.shadeActive)
        assertThat(checkNotNull(power).iconTint)
        assertThat(checkNotNull(power).backgroundColorFallback).isEqualTo(R.attr.shadeActive)
        assertThat(checkNotNull(power).iconTintFallback)
            .isEqualTo(Utils.getColorAttrDefaultColor(themedContext, R.attr.onShadeActive))
    }

@@ -189,14 +189,14 @@ class FooterActionsViewModelTest : SysuiTestCase() {
        assertThat(userSwitcher).isNotNull()
        assertThat(userSwitcher!!.icon)
            .isEqualTo(Icon.Loaded(picture, ContentDescription.Loaded("Signed in as foo")))
        assertThat(userSwitcher.backgroundColor).isEqualTo(R.attr.shadeInactive)
        assertThat(userSwitcher.backgroundColorFallback).isEqualTo(R.attr.shadeInactive)

        // Change the current user name.
        userSwitcherControllerWrapper.currentUserName = "bar"
        assertThat(currentUserSwitcher()?.icon?.contentDescription)
            .isEqualTo(ContentDescription.Loaded("Signed in as bar"))

        fun iconTint(): Int? = currentUserSwitcher()!!.iconTint
        fun iconTint(): Int? = currentUserSwitcher()!!.iconTintFallback

        // We tint the icon if the current user is not the guest.
        assertThat(iconTint()).isNull()
+45 −7
Original line number Diff line number Diff line
@@ -20,17 +20,55 @@ import android.annotation.AttrRes
import android.annotation.ColorInt
import androidx.compose.runtime.Stable
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.res.R

/**
 * A ViewModel for a simple footer actions button. This is used for the user switcher, settings and
 * power buttons.
 */
@Stable
data class FooterActionsButtonViewModel(
    val id: Int,
    val icon: Icon,
    @ColorInt val iconTint: Int?,
    @AttrRes val backgroundColor: Int,
    val onClick: (Expandable) -> Unit,
sealed interface FooterActionsButtonViewModel {
    val id: Int
    val icon: Icon
    val iconTintFallback: Int?
    val backgroundColorFallback: Int
    val onClick: (Expandable) -> Unit

    data class UserSwitcherViewModel(
        override val icon: Icon,
        @ColorInt override val iconTintFallback: Int?,
        @AttrRes override val backgroundColorFallback: Int,
        override val onClick: (Expandable) -> Unit,
    ) : FooterActionsButtonViewModel {
        override val id: Int = R.id.multi_user_switch
    }

    data class SettingsActionViewModel(
        @ColorInt override val iconTintFallback: Int?,
        @AttrRes override val backgroundColorFallback: Int,
        override val onClick: (Expandable) -> Unit,
    ) : FooterActionsButtonViewModel {
        override val id: Int = R.id.settings_button_container
        override val icon: Icon =
            Icon.Resource(
                R.drawable.ic_settings,
                ContentDescription.Resource(R.string.accessibility_quick_settings_settings),
            )
    }

    data class PowerActionViewModel(
        val isOnDualShade: Boolean,
        @ColorInt override val iconTintFallback: Int?,
        @AttrRes override val backgroundColorFallback: Int,
        override val onClick: (Expandable) -> Unit,
    ) : FooterActionsButtonViewModel {
        override val id: Int = R.id.pm_lite
        override val icon: Icon =
            Icon.Resource(
                android.R.drawable.ic_lock_power_off,
                ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu),
            )
    }
}
+16 −22
Original line number Diff line number Diff line
@@ -37,6 +37,9 @@ import com.android.systemui.qs.flags.QsInCompose
import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsButtonViewModel.PowerActionViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsButtonViewModel.SettingsActionViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsButtonViewModel.UserSwitcherViewModel
import com.android.systemui.qs.panels.domain.interactor.TextFeedbackInteractor
import com.android.systemui.qs.panels.domain.model.TextFeedbackModel
import com.android.systemui.qs.panels.ui.viewmodel.TextFeedbackContentViewModel.Companion.load
@@ -393,8 +396,7 @@ fun userSwitcherButtonViewModel(
    onUserSwitcherClicked: (Expandable) -> Unit,
): FooterActionsButtonViewModel {
    val icon = status.currentUserImage!!
    return FooterActionsButtonViewModel(
        id = R.id.multi_user_switch,
    return UserSwitcherViewModel(
        icon =
            Icon.Loaded(
                icon,
@@ -402,8 +404,8 @@ fun userSwitcherButtonViewModel(
                    userSwitcherContentDescription(qsThemedContext, status.currentUserName)
                ),
            ),
        iconTint = null,
        backgroundColor = R.attr.shadeInactive,
        iconTintFallback = null,
        backgroundColorFallback = R.attr.shadeInactive,
        onClick = onUserSwitcherClicked,
    )
}
@@ -421,15 +423,11 @@ fun settingsButtonViewModel(
    qsThemedContext: Context,
    onSettingsButtonClicked: (Expandable) -> Unit,
): FooterActionsButtonViewModel {
    return FooterActionsButtonViewModel(
        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),
        backgroundColor = R.attr.shadeInactive,
        onSettingsButtonClicked,
    return SettingsActionViewModel(
        iconTintFallback =
            Utils.getColorAttrDefaultColor(qsThemedContext, R.attr.onShadeInactiveVariant),
        backgroundColorFallback = R.attr.shadeInactive,
        onClick = onSettingsButtonClicked,
    )
}

@@ -449,18 +447,14 @@ fun powerButtonViewModel(
    shadeMode: ShadeMode,
): FooterActionsButtonViewModel {
    val isDualShade = shadeMode is ShadeMode.Dual
    return FooterActionsButtonViewModel(
        id = R.id.pm_lite,
        Icon.Resource(
            android.R.drawable.ic_lock_power_off,
            ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu),
        ),
        iconTint =
    return PowerActionViewModel(
        isOnDualShade = isDualShade,
        iconTintFallback =
            Utils.getColorAttrDefaultColor(
                qsThemedContext,
                if (isDualShade) R.attr.onShadeInactiveVariant else R.attr.onShadeActive,
            ),
        backgroundColor = if (isDualShade) R.attr.shadeInactive else R.attr.shadeActive,
        onPowerButtonClicked,
        backgroundColorFallback = if (isDualShade) R.attr.shadeInactive else R.attr.shadeActive,
        onClick = onPowerButtonClicked,
    )
}