1 package com.android.permissioncontroller.permission.ui.wear.theme
2 
3 import android.content.Context
4 import android.os.Build
5 import androidx.annotation.RequiresApi
6 import androidx.annotation.StringRes
7 import androidx.annotation.VisibleForTesting
8 import androidx.compose.runtime.Composable
9 import androidx.compose.ui.graphics.Color
10 import androidx.compose.ui.platform.LocalContext
11 import androidx.compose.ui.text.font.DeviceFontFamilyName
12 import androidx.compose.ui.text.font.Font
13 import androidx.compose.ui.text.font.FontFamily
14 import androidx.wear.compose.material.Colors
15 import androidx.wear.compose.material.MaterialTheme
16 import androidx.wear.compose.material.Typography
17 import com.android.permissioncontroller.R
18 
19 /** The Material 3 Theme Wrapper for Supporting RRO. */
20 @Composable
WearPermissionThemenull21 fun WearPermissionTheme(content: @Composable () -> Unit) {
22     val context = LocalContext.current
23     val colors =
24         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
25             overlayColors(context)
26                 .copy(error = MaterialTheme.colors.error, onError = MaterialTheme.colors.onError)
27         } else {
28             MaterialTheme.colors
29         }
30     MaterialTheme(colors = colors, typography = deviceDefaultTypography(context), content = content)
31 }
32 
33 /**
34  * Creates a dynamic color maps that can be overlaid. 100 - Lightest shade; 0 - Darkest Shade; In
35  * wear we only support dark theme for the time being. Thus the fill colors and variants are dark
36  * and anything on top is light. We will use this custom redirection until wear compose material
37  * supports color scheming.
38  *
39  * The mapping is best case match on wear material color tokens from
40  * /android/clockwork/common/wearable/wearmaterial/color/res/values/color-tokens.xml
41  *
42  * @param context The context required to get system resource data.
43  */
44 @RequiresApi(Build.VERSION_CODES.S)
45 @VisibleForTesting
overlayColorsnull46 internal fun overlayColors(context: Context): Colors {
47     val tonalPalette = dynamicTonalPalette(context)
48     return Colors(
49         background = Color.Black,
50         onBackground = Color.White,
51         primary = tonalPalette.primary90,
52         primaryVariant = tonalPalette.primary80,
53         onPrimary = tonalPalette.primary10,
54         secondary = tonalPalette.tertiary90,
55         secondaryVariant = tonalPalette.tertiary60,
56         onSecondary = tonalPalette.tertiary10,
57         surface = tonalPalette.neutral20,
58         onSurface = tonalPalette.neutral95,
59         onSurfaceVariant = tonalPalette.neutralVariant80,
60     )
61 }
62 
fontFamilynull63 private fun fontFamily(context: Context, @StringRes id: Int): FontFamily {
64     val typefaceName = context.resources.getString(id)
65     val font = Font(familyName = DeviceFontFamilyName(typefaceName))
66     return FontFamily(font)
67 }
68 
69 /*
70  Only customizes font family. The material 3 roles to 2.5 are mapped to the best case matching of
71  google3/java/com/google/android/wearable/libraries/compose/theme/GoogleMaterialTheme.kt
72 */
deviceDefaultTypographynull73 internal fun deviceDefaultTypography(context: Context): Typography {
74     val defaultTypography = Typography()
75     return Typography(
76         display1 =
77             defaultTypography.display1.copy(
78                 fontFamily =
79                     fontFamily(context, R.string.wear_material_compose_display_1_font_family)
80             ),
81         display2 =
82             defaultTypography.display2.copy(
83                 fontFamily =
84                     fontFamily(context, R.string.wear_material_compose_display_2_font_family)
85             ),
86         display3 =
87             defaultTypography.display3.copy(
88                 fontFamily =
89                     fontFamily(context, R.string.wear_material_compose_display_3_font_family)
90             ),
91         title1 =
92             defaultTypography.title1.copy(
93                 fontFamily = fontFamily(context, R.string.wear_material_compose_title_1_font_family)
94             ),
95         title2 =
96             defaultTypography.title2.copy(
97                 fontFamily = fontFamily(context, R.string.wear_material_compose_title_2_font_family)
98             ),
99         title3 =
100             defaultTypography.title3.copy(
101                 fontFamily = fontFamily(context, R.string.wear_material_compose_title_3_font_family)
102             ),
103         body1 =
104             defaultTypography.body1.copy(
105                 fontFamily = fontFamily(context, R.string.wear_material_compose_body_1_font_family)
106             ),
107         body2 =
108             defaultTypography.body2.copy(
109                 fontFamily = fontFamily(context, R.string.wear_material_compose_body_2_font_family)
110             ),
111         button =
112             defaultTypography.button.copy(
113                 fontFamily = fontFamily(context, R.string.wear_material_compose_button_font_family)
114             ),
115         caption1 =
116             defaultTypography.caption1.copy(
117                 fontFamily =
118                     fontFamily(context, R.string.wear_material_compose_caption_1_font_family)
119             ),
120         caption2 =
121             defaultTypography.caption2.copy(
122                 fontFamily =
123                     fontFamily(context, R.string.wear_material_compose_caption_2_font_family)
124             ),
125         caption3 =
126             defaultTypography.caption3.copy(
127                 fontFamily =
128                     fontFamily(context, R.string.wear_material_compose_caption_3_font_family)
129             ),
130     )
131 }
132