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

Commit b6beb2f4 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[Spa] Add material color map" into main

parents 4e476e85 09fd13fc
Loading
Loading
Loading
Loading
+1 −44
Original line number Diff line number Diff line
@@ -16,24 +16,15 @@

package com.android.settingslib.spa.widget.ui

import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.res.colorResource
import com.airbnb.lottie.LottieProperty
import com.airbnb.lottie.compose.LottieAnimation
import com.airbnb.lottie.compose.LottieCompositionSpec
import com.airbnb.lottie.compose.LottieConstants
import com.airbnb.lottie.compose.animateLottieCompositionAsState
import com.airbnb.lottie.compose.rememberLottieComposition
import com.airbnb.lottie.compose.rememberLottieDynamicProperties
import com.airbnb.lottie.compose.rememberLottieDynamicProperty
import com.android.settingslib.color.R

@Composable
fun Lottie(resId: Int, modifier: Modifier = Modifier) {
@@ -45,48 +36,14 @@ fun Lottie(spec: LottieCompositionSpec, modifier: Modifier = Modifier) {
    Box(modifier = modifier) { BaseLottie(spec) }
}

object LottieColorUtils {
    private val DARK_TO_LIGHT_THEME_COLOR_MAP =
        mapOf(
            ".grey200" to R.color.settingslib_color_grey800,
            ".grey600" to R.color.settingslib_color_grey400,
            ".grey800" to R.color.settingslib_color_grey300,
            ".grey900" to R.color.settingslib_color_grey50,
            ".red400" to R.color.settingslib_color_red600,
            ".black" to android.R.color.white,
            ".blue400" to R.color.settingslib_color_blue600,
            ".green400" to R.color.settingslib_color_green600,
            ".green200" to R.color.settingslib_color_green500,
            ".red200" to R.color.settingslib_color_red500,
            ".cream" to R.color.settingslib_color_charcoal,
        )

    @Composable
    private fun getDefaultPropertiesList() =
        DARK_TO_LIGHT_THEME_COLOR_MAP.map { (key, colorRes) ->
            val color = colorResource(colorRes).toArgb()
            rememberLottieDynamicProperty(
                property = LottieProperty.COLOR_FILTER,
                keyPath = arrayOf("**", key, "**"),
            ) {
                PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)
            }
        }

    @Composable
    fun getDefaultDynamicProperties() =
        rememberLottieDynamicProperties(*getDefaultPropertiesList().toTypedArray())
}

@Composable
private fun BaseLottie(spec: LottieCompositionSpec) {
    val composition by rememberLottieComposition(spec)
    val progress by
        animateLottieCompositionAsState(composition, iterations = LottieConstants.IterateForever)
    val isLightMode = !isSystemInDarkTheme()
    LottieAnimation(
        composition = composition,
        dynamicProperties = LottieColorUtils.getDefaultDynamicProperties().takeIf { isLightMode },
        dynamicProperties = LottieColorUtils.getDefaultDynamicProperties(),
        progress = { progress },
    )
}
+125 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settingslib.spa.widget.ui

import android.graphics.ColorFilter
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.res.colorResource
import com.airbnb.lottie.LottieProperty
import com.airbnb.lottie.compose.LottieDynamicProperty
import com.airbnb.lottie.compose.rememberLottieDynamicProperties
import com.airbnb.lottie.compose.rememberLottieDynamicProperty
import com.android.settingslib.color.R

internal object LottieColorUtils {
    private val DARK_TO_LIGHT_THEME_COLOR_MAP =
        mapOf(
            ".grey200" to R.color.settingslib_color_grey800,
            ".grey600" to R.color.settingslib_color_grey400,
            ".grey800" to R.color.settingslib_color_grey300,
            ".grey900" to R.color.settingslib_color_grey50,
            ".red400" to R.color.settingslib_color_red600,
            ".black" to android.R.color.white,
            ".blue400" to R.color.settingslib_color_blue600,
            ".green400" to R.color.settingslib_color_green600,
            ".green200" to R.color.settingslib_color_green500,
            ".red200" to R.color.settingslib_color_red500,
            ".cream" to R.color.settingslib_color_charcoal,
        )

    @Composable
    private fun getMaterialColorMap(): Map<String, Color> =
        mapOf(
            ".primary" to MaterialTheme.colorScheme.primary,
            ".onPrimary" to MaterialTheme.colorScheme.onPrimary,
            ".primaryContainer" to MaterialTheme.colorScheme.primaryContainer,
            ".onPrimaryContainer" to MaterialTheme.colorScheme.onPrimaryContainer,
            ".primaryInverse" to MaterialTheme.colorScheme.inversePrimary,
            ".primaryFixed" to MaterialTheme.colorScheme.primaryFixed,
            ".primaryFixedDim" to MaterialTheme.colorScheme.primaryFixedDim,
            ".onPrimaryFixed" to MaterialTheme.colorScheme.onPrimaryFixed,
            ".onPrimaryFixedVariant" to MaterialTheme.colorScheme.onPrimaryFixedVariant,
            ".secondary" to MaterialTheme.colorScheme.secondary,
            ".onSecondary" to MaterialTheme.colorScheme.onSecondary,
            ".secondaryContainer" to MaterialTheme.colorScheme.secondaryContainer,
            ".onSecondaryContainer" to MaterialTheme.colorScheme.onSecondaryContainer,
            ".secondaryFixed" to MaterialTheme.colorScheme.secondaryFixed,
            ".secondaryFixedDim" to MaterialTheme.colorScheme.secondaryFixedDim,
            ".onSecondaryFixed" to MaterialTheme.colorScheme.onSecondaryFixed,
            ".onSecondaryFixedVariant" to MaterialTheme.colorScheme.onSecondaryFixedVariant,
            ".tertiary" to MaterialTheme.colorScheme.tertiary,
            ".onTertiary" to MaterialTheme.colorScheme.onTertiary,
            ".tertiaryContainer" to MaterialTheme.colorScheme.tertiaryContainer,
            ".onTertiaryContainer" to MaterialTheme.colorScheme.onTertiaryContainer,
            ".tertiaryFixed" to MaterialTheme.colorScheme.tertiaryFixed,
            ".tertiaryFixedDim" to MaterialTheme.colorScheme.tertiaryFixedDim,
            ".onTertiaryFixed" to MaterialTheme.colorScheme.onTertiaryFixed,
            ".onTertiaryFixedVariant" to MaterialTheme.colorScheme.onTertiaryFixedVariant,
            ".error" to MaterialTheme.colorScheme.error,
            ".onError" to MaterialTheme.colorScheme.onError,
            ".errorContainer" to MaterialTheme.colorScheme.errorContainer,
            ".onErrorContainer" to MaterialTheme.colorScheme.onErrorContainer,
            ".outline" to MaterialTheme.colorScheme.outline,
            ".outlineVariant" to MaterialTheme.colorScheme.outlineVariant,
            ".background" to MaterialTheme.colorScheme.background,
            ".onBackground" to MaterialTheme.colorScheme.onBackground,
            ".surface" to MaterialTheme.colorScheme.surface,
            ".onSurface" to MaterialTheme.colorScheme.onSurface,
            ".surfaceVariant" to MaterialTheme.colorScheme.surfaceVariant,
            ".onSurfaceVariant" to MaterialTheme.colorScheme.onSurfaceVariant,
            ".surfaceInverse" to MaterialTheme.colorScheme.inverseSurface,
            ".onSurfaceInverse" to MaterialTheme.colorScheme.inverseOnSurface,
            ".surfaceBright" to MaterialTheme.colorScheme.surfaceBright,
            ".surfaceDim" to MaterialTheme.colorScheme.surfaceDim,
            ".surfaceContainer" to MaterialTheme.colorScheme.surfaceContainer,
            ".surfaceContainerLow" to MaterialTheme.colorScheme.surfaceContainerLow,
            ".surfaceContainerLowest" to MaterialTheme.colorScheme.surfaceContainerLowest,
            ".surfaceContainerHigh" to MaterialTheme.colorScheme.surfaceContainerHigh,
            ".surfaceContainerHighest" to MaterialTheme.colorScheme.surfaceContainerHighest,
        )

    @Composable
    private fun getDefaultPropertiesList(): List<LottieDynamicProperty<ColorFilter>> = buildList {
        if (!isSystemInDarkTheme()) {
            for ((key, colorRes) in DARK_TO_LIGHT_THEME_COLOR_MAP) {
                add(createColorFilter(key, colorResource(colorRes)))
            }
        }
        for ((key, color) in getMaterialColorMap()) {
            add(createColorFilter(key, color))
        }
    }

    @Composable
    private fun createColorFilter(key: String, color: Color): LottieDynamicProperty<ColorFilter> =
        rememberLottieDynamicProperty(
            property = LottieProperty.COLOR_FILTER,
            keyPath = arrayOf("**", key, "**"),
        ) {
            PorterDuffColorFilter(color.toArgb(), PorterDuff.Mode.SRC_ATOP)
        }

    @Composable
    fun getDefaultDynamicProperties() =
        rememberLottieDynamicProperties(*getDefaultPropertiesList().toTypedArray())
}