• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settingslib.spa.framework.theme
18 
19 import android.content.Context
20 import android.os.Build
21 import androidx.annotation.VisibleForTesting
22 import androidx.compose.runtime.Composable
23 import androidx.compose.runtime.remember
24 import androidx.compose.runtime.staticCompositionLocalOf
25 import androidx.compose.ui.graphics.Color
26 import androidx.compose.ui.platform.LocalContext
27 
28 data class SettingsColorScheme(
29     val background: Color = Color.Unspecified,
30     val categoryTitle: Color = Color.Unspecified,
31     val surface: Color = Color.Unspecified,
32     val surfaceHeader: Color = Color.Unspecified,
33     val secondaryText: Color = Color.Unspecified,
34     val primaryContainer: Color = Color.Unspecified,
35     val onPrimaryContainer: Color = Color.Unspecified,
36     val spinnerHeaderContainer: Color = Color.Unspecified,
37     val onSpinnerHeaderContainer: Color = Color.Unspecified,
38     val spinnerItemContainer: Color = Color.Unspecified,
39     val onSpinnerItemContainer: Color = Color.Unspecified,
40 )
41 
<lambda>null42 internal val LocalColorScheme = staticCompositionLocalOf { SettingsColorScheme() }
43 
44 @Composable
settingsColorSchemenull45 internal fun settingsColorScheme(isDarkTheme: Boolean): SettingsColorScheme {
46     val context = LocalContext.current
47     return remember(isDarkTheme) {
48         when {
49             Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
50                 if (isDarkTheme) dynamicDarkColorScheme(context)
51                 else dynamicLightColorScheme(context)
52             }
53             isDarkTheme -> darkColorScheme()
54             else -> lightColorScheme()
55         }
56     }
57 }
58 
59 /**
60  * Creates a light dynamic color scheme.
61  *
62  * Use this function to create a color scheme based off the system wallpaper. If the developer
63  * changes the wallpaper this color scheme will change accordingly. This dynamic scheme is a
64  * light theme variant.
65  *
66  * @param context The context required to get system resource data.
67  */
68 @VisibleForTesting
dynamicLightColorSchemenull69 internal fun dynamicLightColorScheme(context: Context): SettingsColorScheme {
70     val tonalPalette = dynamicTonalPalette(context)
71     return SettingsColorScheme(
72         background = tonalPalette.neutral95,
73         categoryTitle = tonalPalette.primary40,
74         surface = tonalPalette.neutral99,
75         surfaceHeader = tonalPalette.neutral90,
76         secondaryText = tonalPalette.neutralVariant30,
77         primaryContainer = tonalPalette.primary90,
78         onPrimaryContainer = tonalPalette.neutral10,
79         spinnerHeaderContainer = tonalPalette.primary90,
80         onSpinnerHeaderContainer = tonalPalette.neutral10,
81         spinnerItemContainer = tonalPalette.secondary90,
82         onSpinnerItemContainer = tonalPalette.neutralVariant30,
83     )
84 }
85 
86 /**
87  * Creates a dark dynamic color scheme.
88  *
89  * Use this function to create a color scheme based off the system wallpaper. If the developer
90  * changes the wallpaper this color scheme will change accordingly. This dynamic scheme is a dark
91  * theme variant.
92  *
93  * @param context The context required to get system resource data.
94  */
95 @VisibleForTesting
dynamicDarkColorSchemenull96 internal fun dynamicDarkColorScheme(context: Context): SettingsColorScheme {
97     val tonalPalette = dynamicTonalPalette(context)
98     return SettingsColorScheme(
99         background = tonalPalette.neutral10,
100         categoryTitle = tonalPalette.primary90,
101         surface = tonalPalette.neutral20,
102         surfaceHeader = tonalPalette.neutral30,
103         secondaryText = tonalPalette.neutralVariant80,
104         primaryContainer = tonalPalette.secondary90,
105         onPrimaryContainer = tonalPalette.neutral10,
106         spinnerHeaderContainer = tonalPalette.primary90,
107         onSpinnerHeaderContainer = tonalPalette.neutral10,
108         spinnerItemContainer = tonalPalette.secondary90,
109         onSpinnerItemContainer = tonalPalette.neutralVariant30,
110     )
111 }
112 
113 @VisibleForTesting
darkColorSchemenull114 internal fun darkColorScheme(): SettingsColorScheme {
115     val tonalPalette = tonalPalette()
116     return SettingsColorScheme(
117         background = tonalPalette.neutral10,
118         categoryTitle = tonalPalette.primary90,
119         surface = tonalPalette.neutral20,
120         surfaceHeader = tonalPalette.neutral30,
121         secondaryText = tonalPalette.neutralVariant80,
122         primaryContainer = tonalPalette.secondary90,
123         onPrimaryContainer = tonalPalette.neutral10,
124         spinnerHeaderContainer = tonalPalette.primary90,
125         onSpinnerHeaderContainer = tonalPalette.neutral10,
126         spinnerItemContainer = tonalPalette.secondary90,
127         onSpinnerItemContainer = tonalPalette.neutralVariant30,
128     )
129 }
130 
131 @VisibleForTesting
lightColorSchemenull132 internal fun lightColorScheme(): SettingsColorScheme {
133     val tonalPalette = tonalPalette()
134     return SettingsColorScheme(
135         background = tonalPalette.neutral95,
136         categoryTitle = tonalPalette.primary40,
137         surface = tonalPalette.neutral99,
138         surfaceHeader = tonalPalette.neutral90,
139         secondaryText = tonalPalette.neutralVariant30,
140         primaryContainer = tonalPalette.primary90,
141         onPrimaryContainer = tonalPalette.neutral10,
142         spinnerHeaderContainer = tonalPalette.primary90,
143         onSpinnerHeaderContainer = tonalPalette.neutral10,
144         spinnerItemContainer = tonalPalette.secondary90,
145         onSpinnerItemContainer = tonalPalette.neutralVariant30,
146     )
147 }
148