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

Commit 8e1cb658 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Android (Google) Code Review
Browse files

Merge "Introduce LocalAndroidColorScheme to expose Android colors"

parents 7b0313fd 78b3e889
Loading
Loading
Loading
Loading
+74 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.compose.theme

import android.annotation.ColorInt
import android.content.Context
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import com.android.internal.R

/** CompositionLocal used to pass [AndroidColorScheme] down the tree. */
val LocalAndroidColorScheme =
    staticCompositionLocalOf<AndroidColorScheme> {
        throw IllegalStateException(
            "No AndroidColorScheme configured. Make sure to use LocalAndroidColorScheme in a " +
                "Composable surrounded by a SystemUITheme {}."
        )
    }

/**
 * The Android color scheme.
 *
 * Important: Use M3 colors from MaterialTheme.colorScheme whenever possible instead. In the future,
 * most of the colors in this class will be removed in favor of their M3 counterpart.
 */
class AndroidColorScheme internal constructor(private val context: Context) {
    val colorPrimary = getColor(context, R.attr.colorPrimary)
    val colorPrimaryDark = getColor(context, R.attr.colorPrimaryDark)
    val colorAccent = getColor(context, R.attr.colorAccent)
    val colorAccentPrimary = getColor(context, R.attr.colorAccentPrimary)
    val colorAccentSecondary = getColor(context, R.attr.colorAccentSecondary)
    val colorAccentTertiary = getColor(context, R.attr.colorAccentTertiary)
    val colorAccentPrimaryVariant = getColor(context, R.attr.colorAccentPrimaryVariant)
    val colorAccentSecondaryVariant = getColor(context, R.attr.colorAccentSecondaryVariant)
    val colorAccentTertiaryVariant = getColor(context, R.attr.colorAccentTertiaryVariant)
    val colorSurface = getColor(context, R.attr.colorSurface)
    val colorSurfaceHighlight = getColor(context, R.attr.colorSurfaceHighlight)
    val colorSurfaceVariant = getColor(context, R.attr.colorSurfaceVariant)
    val colorSurfaceHeader = getColor(context, R.attr.colorSurfaceHeader)
    val colorError = getColor(context, R.attr.colorError)
    val colorBackground = getColor(context, R.attr.colorBackground)
    val colorBackgroundFloating = getColor(context, R.attr.colorBackgroundFloating)
    val panelColorBackground = getColor(context, R.attr.panelColorBackground)
    val textColorPrimary = getColor(context, R.attr.textColorPrimary)
    val textColorSecondary = getColor(context, R.attr.textColorSecondary)
    val textColorTertiary = getColor(context, R.attr.textColorTertiary)
    val textColorPrimaryInverse = getColor(context, R.attr.textColorPrimaryInverse)
    val textColorSecondaryInverse = getColor(context, R.attr.textColorSecondaryInverse)
    val textColorTertiaryInverse = getColor(context, R.attr.textColorTertiaryInverse)
    val textColorOnAccent = getColor(context, R.attr.textColorOnAccent)
    val colorForeground = getColor(context, R.attr.colorForeground)
    val colorForegroundInverse = getColor(context, R.attr.colorForegroundInverse)

    private fun getColor(context: Context, attr: Int): Color {
        val ta = context.obtainStyledAttributes(intArrayOf(attr))
        @ColorInt val color = ta.getColor(0, 0)
        ta.recycle()
        return Color(color)
    }
}
+9 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import androidx.compose.material3.Typography
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext

/** The Material 3 theme that should wrap all SystemUI Composables. */
@@ -39,7 +40,14 @@ fun SystemUITheme(
        } else {
            dynamicLightColorScheme(context)
        }
    val androidColorScheme = AndroidColorScheme(context)
    val typography = Typography()

    MaterialTheme(colorScheme, typography = typography) { content() }
    MaterialTheme(colorScheme, typography = typography) {
        CompositionLocalProvider(
            LocalAndroidColorScheme provides androidColorScheme,
        ) {
            content()
        }
    }
}
+19 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertThrows
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -35,4 +36,22 @@ class SystemUIThemeTest {

        composeRule.onNodeWithText("foo").assertIsDisplayed()
    }

    @Test
    fun testAndroidColorsAreAvailableInsideTheme() {
        composeRule.setContent {
            SystemUITheme { Text("foo", color = LocalAndroidColorScheme.current.colorAccent) }
        }

        composeRule.onNodeWithText("foo").assertIsDisplayed()
    }

    @Test
    fun testAccessingAndroidColorsWithoutThemeThrows() {
        assertThrows(IllegalStateException::class.java) {
            composeRule.setContent {
                Text("foo", color = LocalAndroidColorScheme.current.colorAccent)
            }
        }
    }
}
+79 −28
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
@@ -32,38 +33,88 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.android.systemui.compose.theme.LocalAndroidColorScheme

/** The screen that shows all the Material 3 colors. */
@Composable
fun ColorsScreen() {
fun MaterialColorsScreen() {
    val colors = MaterialTheme.colorScheme
    LazyColumn {
        item { ColorTile(colors.primary, "primary") }
        item { ColorTile(colors.onPrimary, "onPrimary") }
        item { ColorTile(colors.primaryContainer, "primaryContainer") }
        item { ColorTile(colors.onPrimaryContainer, "onPrimaryContainer") }
        item { ColorTile(colors.inversePrimary, "inversePrimary") }
        item { ColorTile(colors.secondary, "secondary") }
        item { ColorTile(colors.onSecondary, "onSecondary") }
        item { ColorTile(colors.secondaryContainer, "secondaryContainer") }
        item { ColorTile(colors.onSecondaryContainer, "onSecondaryContainer") }
        item { ColorTile(colors.tertiary, "tertiary") }
        item { ColorTile(colors.onTertiary, "onTertiary") }
        item { ColorTile(colors.tertiaryContainer, "tertiaryContainer") }
        item { ColorTile(colors.onTertiaryContainer, "onTertiaryContainer") }
        item { ColorTile(colors.background, "background") }
        item { ColorTile(colors.onBackground, "onBackground") }
        item { ColorTile(colors.surface, "surface") }
        item { ColorTile(colors.onSurface, "onSurface") }
        item { ColorTile(colors.surfaceVariant, "surfaceVariant") }
        item { ColorTile(colors.onSurfaceVariant, "onSurfaceVariant") }
        item { ColorTile(colors.inverseSurface, "inverseSurface") }
        item { ColorTile(colors.inverseOnSurface, "inverseOnSurface") }
        item { ColorTile(colors.error, "error") }
        item { ColorTile(colors.onError, "onError") }
        item { ColorTile(colors.errorContainer, "errorContainer") }
        item { ColorTile(colors.onErrorContainer, "onErrorContainer") }
        item { ColorTile(colors.outline, "outline") }
    ColorsScreen(
        listOf(
            "primary" to colors.primary,
            "onPrimary" to colors.onPrimary,
            "primaryContainer" to colors.primaryContainer,
            "onPrimaryContainer" to colors.onPrimaryContainer,
            "inversePrimary" to colors.inversePrimary,
            "secondary" to colors.secondary,
            "onSecondary" to colors.onSecondary,
            "secondaryContainer" to colors.secondaryContainer,
            "onSecondaryContainer" to colors.onSecondaryContainer,
            "tertiary" to colors.tertiary,
            "onTertiary" to colors.onTertiary,
            "tertiaryContainer" to colors.tertiaryContainer,
            "onTertiaryContainer" to colors.onTertiaryContainer,
            "background" to colors.background,
            "onBackground" to colors.onBackground,
            "surface" to colors.surface,
            "onSurface" to colors.onSurface,
            "surfaceVariant" to colors.surfaceVariant,
            "onSurfaceVariant" to colors.onSurfaceVariant,
            "inverseSurface" to colors.inverseSurface,
            "inverseOnSurface" to colors.inverseOnSurface,
            "error" to colors.error,
            "onError" to colors.onError,
            "errorContainer" to colors.errorContainer,
            "onErrorContainer" to colors.onErrorContainer,
            "outline" to colors.outline,
        )
    )
}

/** The screen that shows all the Android colors. */
@Composable
fun AndroidColorsScreen() {
    val colors = LocalAndroidColorScheme.current
    ColorsScreen(
        listOf(
            "colorPrimary" to colors.colorPrimary,
            "colorPrimaryDark" to colors.colorPrimaryDark,
            "colorAccent" to colors.colorAccent,
            "colorAccentPrimary" to colors.colorAccentPrimary,
            "colorAccentSecondary" to colors.colorAccentSecondary,
            "colorAccentTertiary" to colors.colorAccentTertiary,
            "colorAccentPrimaryVariant" to colors.colorAccentPrimaryVariant,
            "colorAccentSecondaryVariant" to colors.colorAccentSecondaryVariant,
            "colorAccentTertiaryVariant" to colors.colorAccentTertiaryVariant,
            "colorSurface" to colors.colorSurface,
            "colorSurfaceHighlight" to colors.colorSurfaceHighlight,
            "colorSurfaceVariant" to colors.colorSurfaceVariant,
            "colorSurfaceHeader" to colors.colorSurfaceHeader,
            "colorError" to colors.colorError,
            "colorBackground" to colors.colorBackground,
            "colorBackgroundFloating" to colors.colorBackgroundFloating,
            "panelColorBackground" to colors.panelColorBackground,
            "textColorPrimary" to colors.textColorPrimary,
            "textColorSecondary" to colors.textColorSecondary,
            "textColorTertiary" to colors.textColorTertiary,
            "textColorPrimaryInverse" to colors.textColorPrimaryInverse,
            "textColorSecondaryInverse" to colors.textColorSecondaryInverse,
            "textColorTertiaryInverse" to colors.textColorTertiaryInverse,
            "textColorOnAccent" to colors.textColorOnAccent,
            "colorForeground" to colors.colorForeground,
            "colorForegroundInverse" to colors.colorForegroundInverse,
        )
    )
}

@Composable
private fun ColorsScreen(
    colors: List<Pair<String, Color>>,
) {
    LazyColumn(
        Modifier.fillMaxWidth(),
    ) {
        colors.forEach { (name, color) -> item { ColorTile(color, name) } }
    }
}

+4 −2
Original line number Diff line number Diff line
@@ -30,7 +30,8 @@ import com.android.systemui.compose.theme.SystemUITheme
enum class Screen {
    Home,
    Typography,
    Colors,
    MaterialColors,
    AndroidColors,
    ExampleFeature,
}

@@ -49,7 +50,8 @@ private fun MainContent() {
                )
            }
            composable(Screen.Typography.name) { TypographyScreen() }
            composable(Screen.Colors.name) { ColorsScreen() }
            composable(Screen.MaterialColors.name) { MaterialColorsScreen() }
            composable(Screen.AndroidColors.name) { AndroidColorsScreen() }
            composable(Screen.ExampleFeature.name) { ExampleFeatureScreen() }
        }
    }