From 296eaafdeaa97d5c25fbac89bc38fcee6a0f1b49 Mon Sep 17 00:00:00 2001 From: James Williams <66931+jwill@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:28:41 -0700 Subject: [PATCH 1/8] Contrast aware updates. Added colors for standard, medium, and high in both light and dark themes. Added helper function to select contrast level based on values from SysUI controls. Added more variance in application of surface container roles to better indicate elevation and emphasis. --- .../java/com/example/reply/ui/MainActivity.kt | 3 +- .../java/com/example/reply/ui/ReplyApp.kt | 2 +- .../com/example/reply/ui/ReplyListContent.kt | 2 +- .../reply/ui/components/ReplyEmailListItem.kt | 6 +- .../ui/components/ReplyEmailThreadItem.kt | 18 +- .../navigation/ReplyNavigationComponents.kt | 9 +- .../java/com/example/reply/ui/theme/Color.kt | 276 ++++++++++--- .../java/com/example/reply/ui/theme/Theme.kt | 365 +++++++++++++++--- 8 files changed, 545 insertions(+), 136 deletions(-) diff --git a/Reply/app/src/main/java/com/example/reply/ui/MainActivity.kt b/Reply/app/src/main/java/com/example/reply/ui/MainActivity.kt index ca66807e8d..83e8a471e8 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/MainActivity.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/MainActivity.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.example.reply.data.local.LocalEmailsDataProvider +import com.example.reply.ui.theme.ContrastAwareReplyTheme import com.example.reply.ui.theme.ReplyTheme import com.google.accompanist.adaptive.calculateDisplayFeatures @@ -44,7 +45,7 @@ class MainActivity : ComponentActivity() { super.onCreate(savedInstanceState) setContent { - ReplyTheme { + ContrastAwareReplyTheme { val windowSize = calculateWindowSizeClass(this) val displayFeatures = calculateDisplayFeatures(this) val uiState by viewModel.uiState.collectAsStateWithLifecycle() diff --git a/Reply/app/src/main/java/com/example/reply/ui/ReplyApp.kt b/Reply/app/src/main/java/com/example/reply/ui/ReplyApp.kt index ec0a5826df..891c3d4a77 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/ReplyApp.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/ReplyApp.kt @@ -255,7 +255,7 @@ fun ReplyAppContent( Column( modifier = Modifier .fillMaxSize() - .background(MaterialTheme.colorScheme.inverseOnSurface) + .background(MaterialTheme.colorScheme.surfaceContainerLow) ) { ReplyNavHost( navController = navController, diff --git a/Reply/app/src/main/java/com/example/reply/ui/ReplyListContent.kt b/Reply/app/src/main/java/com/example/reply/ui/ReplyListContent.kt index 1f7f8a1727..ba82be61dd 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/ReplyListContent.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/ReplyListContent.kt @@ -181,7 +181,7 @@ fun ReplyEmailList( }, modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp) + .padding(horizontal = 16.dp, vertical = 16.dp) ) LazyColumn( diff --git a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailListItem.kt b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailListItem.kt index 15a17a041b..d726d2b12d 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailListItem.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailListItem.kt @@ -115,14 +115,13 @@ fun ReplyEmailListItem( Text( text = email.createdAt, style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.outline ) } IconButton( onClick = { /*TODO*/ }, modifier = Modifier .clip(CircleShape) - .background(MaterialTheme.colorScheme.surface) + .background(MaterialTheme.colorScheme.surfaceContainerHigh) ) { Icon( imageVector = Icons.Default.StarBorder, @@ -135,15 +134,12 @@ fun ReplyEmailListItem( Text( text = email.subject, style = MaterialTheme.typography.bodyLarge, - color = if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer - else MaterialTheme.colorScheme.onSurface, modifier = Modifier.padding(top = 12.dp, bottom = 8.dp), ) Text( text = email.body, style = MaterialTheme.typography.bodyMedium, maxLines = 2, - color = MaterialTheme.colorScheme.onSurfaceVariant, overflow = TextOverflow.Ellipsis ) } diff --git a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt index 933eeb86ad..99a4faba76 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt @@ -20,8 +20,10 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column 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.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.StarBorder @@ -34,6 +36,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text +import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -50,7 +53,7 @@ fun ReplyEmailThreadItem( ) { Card( modifier = modifier.padding(horizontal = 16.dp, vertical = 4.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface) + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceContainerHigh) ) { Column( modifier = Modifier @@ -82,7 +85,7 @@ fun ReplyEmailThreadItem( onClick = { /*TODO*/ }, modifier = Modifier .clip(CircleShape) - .background(MaterialTheme.colorScheme.surface) + .background(MaterialTheme.colorScheme.surfaceContainer) ) { Icon( imageVector = Icons.Default.StarBorder, @@ -107,31 +110,32 @@ fun ReplyEmailThreadItem( Row( modifier = Modifier .fillMaxWidth() - .padding(vertical = 20.dp), + .padding(top = 20.dp, bottom = 8.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), ) { Button( onClick = { /*TODO*/ }, modifier = Modifier.weight(1f), colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.inverseOnSurface + containerColor = MaterialTheme.colorScheme.surfaceBright ) ) { Text( text = stringResource(id = R.string.reply), - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurface ) } + Spacer(modifier = Modifier.width(8.dp)) Button( onClick = { /*TODO*/ }, modifier = Modifier.weight(1f), colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.inverseOnSurface + containerColor = MaterialTheme.colorScheme.surfaceBright ) ) { Text( text = stringResource(id = R.string.reply_all), - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurface ) } } diff --git a/Reply/app/src/main/java/com/example/reply/ui/navigation/ReplyNavigationComponents.kt b/Reply/app/src/main/java/com/example/reply/ui/navigation/ReplyNavigationComponents.kt index 764bc740b4..c2de736ccb 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/navigation/ReplyNavigationComponents.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/navigation/ReplyNavigationComponents.kt @@ -30,6 +30,7 @@ import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.MenuOpen import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Menu import androidx.compose.material.icons.filled.MenuOpen @@ -157,12 +158,12 @@ fun PermanentNavigationDrawerContent( ) { PermanentDrawerSheet( modifier = Modifier.sizeIn(minWidth = 200.dp, maxWidth = 300.dp), - drawerContainerColor = MaterialTheme.colorScheme.inverseOnSurface, + drawerContainerColor = MaterialTheme.colorScheme.surfaceContainerHigh, ) { // TODO remove custom nav drawer content positioning when NavDrawer component supports it. ticket : b/232495216 Layout( modifier = Modifier - .background(MaterialTheme.colorScheme.inverseOnSurface) + .background(MaterialTheme.colorScheme.surfaceContainerHigh) .padding(16.dp), content = { Column( @@ -188,7 +189,7 @@ fun PermanentNavigationDrawerContent( Icon( imageVector = Icons.Default.Edit, contentDescription = stringResource(id = R.string.edit), - modifier = Modifier.size(18.dp) + modifier = Modifier.size(24.dp) ) Text( text = stringResource(id = R.string.compose), @@ -268,7 +269,7 @@ fun ModalNavigationDrawerContent( ) IconButton(onClick = onDrawerClicked) { Icon( - imageVector = Icons.Default.MenuOpen, + imageVector = Icons.AutoMirrored.Filled.MenuOpen, contentDescription = stringResource(id = R.string.navigation_drawer) ) } diff --git a/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt b/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt index fdd91410fb..3bb6f7e5a7 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright 2024 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. @@ -15,62 +15,230 @@ */ package com.example.reply.ui.theme - import androidx.compose.ui.graphics.Color // Generate them via theme builder // https://material-foundation.github.io/material-theme-builder/#/custom -val replyLightPrimary = Color(0xFF825500) -val replyLightOnPrimary = Color(0xFFFFFFFF) -val replyLightPrimaryContainer = Color(0xFFFFDDAE) -val replyLightOnPrimaryContainer = Color(0xFF2A1800) -val replyLightSecondary = Color(0xFF6F5B40) -val replyLightOnSecondary = Color(0xFFFFFFFF) -val replyLightSecondaryContainer = Color(0xFFFADEBC) -val replyLightOnSecondaryContainer = Color(0xFF271904) -val replyLightTertiary = Color(0xFF516440) -val replyLightOnTertiary = Color(0xFFFFFFFF) -val replyLightTertiaryContainer = Color(0xFFD3EABC) -val replyLightOnTertiaryContainer = Color(0xFF102004) -val replyLightError = Color(0xFFBA1B1B) -val replyLightErrorContainer = Color(0xFFFFDAD4) -val replyLightOnError = Color(0xFFFFFFFF) -val replyLightOnErrorContainer = Color(0xFF410001) -val replyLightBackground = Color(0xFFFCFCFC) -val replyLightOnBackground = Color(0xFF1F1B16) -val replyLightSurface = Color(0xFFFCFCFC) -val replyLightOnSurface = Color(0xFF1F1B16) -val replyLightSurfaceVariant = Color(0xFFF0E0CF) -val replyLightOnSurfaceVariant = Color(0xFF4F4539) -val replyLightOutline = Color(0xFF817567) -val replyLightInverseOnSurface = Color(0xFFF9EFE6) -val replyLightInverseSurface = Color(0xFF34302A) -val replyLightPrimaryInverse = Color(0xFFFFB945) +val primaryLight = Color(0xFF805610) +val onPrimaryLight = Color(0xFFFFFFFF) +val primaryContainerLight = Color(0xFFFFDDB3) +val onPrimaryContainerLight = Color(0xFF291800) +val secondaryLight = Color(0xFF6F5B40) +val onSecondaryLight = Color(0xFFFFFFFF) +val secondaryContainerLight = Color(0xFFFBDEBC) +val onSecondaryContainerLight = Color(0xFF271904) +val tertiaryLight = Color(0xFF51643F) +val onTertiaryLight = Color(0xFFFFFFFF) +val tertiaryContainerLight = Color(0xFFD4EABB) +val onTertiaryContainerLight = Color(0xFF102004) +val errorLight = Color(0xFFBA1A1A) +val onErrorLight = Color(0xFFFFFFFF) +val errorContainerLight = Color(0xFFFFDAD6) +val onErrorContainerLight = Color(0xFF410002) +val backgroundLight = Color(0xFFFFF8F4) +val onBackgroundLight = Color(0xFF201B13) +val surfaceLight = Color(0xFFFFF8F4) +val onSurfaceLight = Color(0xFF201B13) +val surfaceVariantLight = Color(0xFFF0E0CF) +val onSurfaceVariantLight = Color(0xFF4F4539) +val outlineLight = Color(0xFF817567) +val outlineVariantLight = Color(0xFFD3C4B4) +val scrimLight = Color(0xFF000000) +val inverseSurfaceLight = Color(0xFF362F27) +val inverseOnSurfaceLight = Color(0xFFFCEFE2) +val inversePrimaryLight = Color(0xFFF4BD6F) +val surfaceDimLight = Color(0xFFE4D8CC) +val surfaceBrightLight = Color(0xFFFFF8F4) +val surfaceContainerLowestLight = Color(0xFFFFFFFF) +val surfaceContainerLowLight = Color(0xFFFFF1E5) +val surfaceContainerLight = Color(0xFFF9ECDF) +val surfaceContainerHighLight = Color(0xFFF3E6DA) +val surfaceContainerHighestLight = Color(0xFFEDE0D4) + +val primaryLightMediumContrast = Color(0xFF5D3C00) +val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +val primaryContainerLightMediumContrast = Color(0xFF996C26) +val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val secondaryLightMediumContrast = Color(0xFF524027) +val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +val secondaryContainerLightMediumContrast = Color(0xFF877155) +val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val tertiaryLightMediumContrast = Color(0xFF364826) +val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +val tertiaryContainerLightMediumContrast = Color(0xFF677B54) +val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val errorLightMediumContrast = Color(0xFF8C0009) +val onErrorLightMediumContrast = Color(0xFFFFFFFF) +val errorContainerLightMediumContrast = Color(0xFFDA342E) +val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +val backgroundLightMediumContrast = Color(0xFFFFF8F4) +val onBackgroundLightMediumContrast = Color(0xFF201B13) +val surfaceLightMediumContrast = Color(0xFFFFF8F4) +val onSurfaceLightMediumContrast = Color(0xFF201B13) +val surfaceVariantLightMediumContrast = Color(0xFFF0E0CF) +val onSurfaceVariantLightMediumContrast = Color(0xFF4B4135) +val outlineLightMediumContrast = Color(0xFF685D50) +val outlineVariantLightMediumContrast = Color(0xFF85796B) +val scrimLightMediumContrast = Color(0xFF000000) +val inverseSurfaceLightMediumContrast = Color(0xFF362F27) +val inverseOnSurfaceLightMediumContrast = Color(0xFFFCEFE2) +val inversePrimaryLightMediumContrast = Color(0xFFF4BD6F) +val surfaceDimLightMediumContrast = Color(0xFFE4D8CC) +val surfaceBrightLightMediumContrast = Color(0xFFFFF8F4) +val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +val surfaceContainerLowLightMediumContrast = Color(0xFFFFF1E5) +val surfaceContainerLightMediumContrast = Color(0xFFF9ECDF) +val surfaceContainerHighLightMediumContrast = Color(0xFFF3E6DA) +val surfaceContainerHighestLightMediumContrast = Color(0xFFEDE0D4) + +val primaryLightHighContrast = Color(0xFF321E00) +val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +val primaryContainerLightHighContrast = Color(0xFF5D3C00) +val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +val secondaryLightHighContrast = Color(0xFF2E1F09) +val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +val secondaryContainerLightHighContrast = Color(0xFF524027) +val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +val tertiaryLightHighContrast = Color(0xFF172608) +val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +val tertiaryContainerLightHighContrast = Color(0xFF364826) +val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +val errorLightHighContrast = Color(0xFF4E0002) +val onErrorLightHighContrast = Color(0xFFFFFFFF) +val errorContainerLightHighContrast = Color(0xFF8C0009) +val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +val backgroundLightHighContrast = Color(0xFFFFF8F4) +val onBackgroundLightHighContrast = Color(0xFF201B13) +val surfaceLightHighContrast = Color(0xFFFFF8F4) +val onSurfaceLightHighContrast = Color(0xFF000000) +val surfaceVariantLightHighContrast = Color(0xFFF0E0CF) +val onSurfaceVariantLightHighContrast = Color(0xFF2B2318) +val outlineLightHighContrast = Color(0xFF4B4135) +val outlineVariantLightHighContrast = Color(0xFF4B4135) +val scrimLightHighContrast = Color(0xFF000000) +val inverseSurfaceLightHighContrast = Color(0xFF362F27) +val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +val inversePrimaryLightHighContrast = Color(0xFFFFE9CF) +val surfaceDimLightHighContrast = Color(0xFFE4D8CC) +val surfaceBrightLightHighContrast = Color(0xFFFFF8F4) +val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +val surfaceContainerLowLightHighContrast = Color(0xFFFFF1E5) +val surfaceContainerLightHighContrast = Color(0xFFF9ECDF) +val surfaceContainerHighLightHighContrast = Color(0xFFF3E6DA) +val surfaceContainerHighestLightHighContrast = Color(0xFFEDE0D4) + +val primaryDark = Color(0xFFF4BD6F) +val onPrimaryDark = Color(0xFF452B00) +val primaryContainerDark = Color(0xFF633F00) +val onPrimaryContainerDark = Color(0xFFFFDDB3) +val secondaryDark = Color(0xFFDDC2A1) +val onSecondaryDark = Color(0xFF3E2D16) +val secondaryContainerDark = Color(0xFF56442A) +val onSecondaryContainerDark = Color(0xFFFBDEBC) +val tertiaryDark = Color(0xFFB8CEA1) +val onTertiaryDark = Color(0xFF243515) +val tertiaryContainerDark = Color(0xFF3A4C2A) +val onTertiaryContainerDark = Color(0xFFD4EABB) +val errorDark = Color(0xFFFFB4AB) +val onErrorDark = Color(0xFF690005) +val errorContainerDark = Color(0xFF93000A) +val onErrorContainerDark = Color(0xFFFFDAD6) +val backgroundDark = Color(0xFF18120B) +val onBackgroundDark = Color(0xFFEDE0D4) +val surfaceDark = Color(0xFF18120B) +val onSurfaceDark = Color(0xFFEDE0D4) +val surfaceVariantDark = Color(0xFF4F4539) +val onSurfaceVariantDark = Color(0xFFD3C4B4) +val outlineDark = Color(0xFF9C8F80) +val outlineVariantDark = Color(0xFF4F4539) +val scrimDark = Color(0xFF000000) +val inverseSurfaceDark = Color(0xFFEDE0D4) +val inverseOnSurfaceDark = Color(0xFF362F27) +val inversePrimaryDark = Color(0xFF805610) +val surfaceDimDark = Color(0xFF18120B) +val surfaceBrightDark = Color(0xFF3F3830) +val surfaceContainerLowestDark = Color(0xFF120D07) +val surfaceContainerLowDark = Color(0xFF201B13) +val surfaceContainerDark = Color(0xFF251F17) +val surfaceContainerHighDark = Color(0xFF2F2921) +val surfaceContainerHighestDark = Color(0xFF3B342B) + +val primaryDarkMediumContrast = Color(0xFFF9C172) +val onPrimaryDarkMediumContrast = Color(0xFF221300) +val primaryContainerDarkMediumContrast = Color(0xFFB9883F) +val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +val secondaryDarkMediumContrast = Color(0xFFE2C6A5) +val onSecondaryDarkMediumContrast = Color(0xFF211402) +val secondaryContainerDarkMediumContrast = Color(0xFFA58D6F) +val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) +val tertiaryDarkMediumContrast = Color(0xFFBCD2A5) +val onTertiaryDarkMediumContrast = Color(0xFF0B1A01) +val tertiaryContainerDarkMediumContrast = Color(0xFF83976E) +val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) +val errorDarkMediumContrast = Color(0xFFFFBAB1) +val onErrorDarkMediumContrast = Color(0xFF370001) +val errorContainerDarkMediumContrast = Color(0xFFFF5449) +val onErrorContainerDarkMediumContrast = Color(0xFF000000) +val backgroundDarkMediumContrast = Color(0xFF18120B) +val onBackgroundDarkMediumContrast = Color(0xFFEDE0D4) +val surfaceDarkMediumContrast = Color(0xFF18120B) +val onSurfaceDarkMediumContrast = Color(0xFFFFFAF7) +val surfaceVariantDarkMediumContrast = Color(0xFF4F4539) +val onSurfaceVariantDarkMediumContrast = Color(0xFFD7C8B8) +val outlineDarkMediumContrast = Color(0xFFAEA192) +val outlineVariantDarkMediumContrast = Color(0xFF8E8173) +val scrimDarkMediumContrast = Color(0xFF000000) +val inverseSurfaceDarkMediumContrast = Color(0xFFEDE0D4) +val inverseOnSurfaceDarkMediumContrast = Color(0xFF302921) +val inversePrimaryDarkMediumContrast = Color(0xFF644100) +val surfaceDimDarkMediumContrast = Color(0xFF18120B) +val surfaceBrightDarkMediumContrast = Color(0xFF3F3830) +val surfaceContainerLowestDarkMediumContrast = Color(0xFF120D07) +val surfaceContainerLowDarkMediumContrast = Color(0xFF201B13) +val surfaceContainerDarkMediumContrast = Color(0xFF251F17) +val surfaceContainerHighDarkMediumContrast = Color(0xFF2F2921) +val surfaceContainerHighestDarkMediumContrast = Color(0xFF3B342B) + +val primaryDarkHighContrast = Color(0xFFFFFAF7) +val onPrimaryDarkHighContrast = Color(0xFF000000) +val primaryContainerDarkHighContrast = Color(0xFFF9C172) +val onPrimaryContainerDarkHighContrast = Color(0xFF000000) +val secondaryDarkHighContrast = Color(0xFFFFFAF7) +val onSecondaryDarkHighContrast = Color(0xFF000000) +val secondaryContainerDarkHighContrast = Color(0xFFE2C6A5) +val onSecondaryContainerDarkHighContrast = Color(0xFF000000) +val tertiaryDarkHighContrast = Color(0xFFF3FFE2) +val onTertiaryDarkHighContrast = Color(0xFF000000) +val tertiaryContainerDarkHighContrast = Color(0xFFBCD2A5) +val onTertiaryContainerDarkHighContrast = Color(0xFF000000) +val errorDarkHighContrast = Color(0xFFFFF9F9) +val onErrorDarkHighContrast = Color(0xFF000000) +val errorContainerDarkHighContrast = Color(0xFFFFBAB1) +val onErrorContainerDarkHighContrast = Color(0xFF000000) +val backgroundDarkHighContrast = Color(0xFF18120B) +val onBackgroundDarkHighContrast = Color(0xFFEDE0D4) +val surfaceDarkHighContrast = Color(0xFF18120B) +val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +val surfaceVariantDarkHighContrast = Color(0xFF4F4539) +val onSurfaceVariantDarkHighContrast = Color(0xFFFFFAF7) +val outlineDarkHighContrast = Color(0xFFD7C8B8) +val outlineVariantDarkHighContrast = Color(0xFFD7C8B8) +val scrimDarkHighContrast = Color(0xFF000000) +val inverseSurfaceDarkHighContrast = Color(0xFFEDE0D4) +val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +val inversePrimaryDarkHighContrast = Color(0xFF3C2500) +val surfaceDimDarkHighContrast = Color(0xFF18120B) +val surfaceBrightDarkHighContrast = Color(0xFF3F3830) +val surfaceContainerLowestDarkHighContrast = Color(0xFF120D07) +val surfaceContainerLowDarkHighContrast = Color(0xFF201B13) +val surfaceContainerDarkHighContrast = Color(0xFF251F17) +val surfaceContainerHighDarkHighContrast = Color(0xFF2F2921) +val surfaceContainerHighestDarkHighContrast = Color(0xFF3B342B) + + + + + + -val replyDarkPrimary = Color(0xFFFFB945) -val replyDarkOnPrimary = Color(0xFF452B00) -val replyDarkPrimaryContainer = Color(0xFF624000) -val replyDarkOnPrimaryContainer = Color(0xFFFFDDAE) -val replyDarkSecondary = Color(0xFFDDC3A2) -val replyDarkOnSecondary = Color(0xFF3E2E16) -val replyDarkSecondaryContainer = Color(0xFF56442B) -val replyDarkOnSecondaryContainer = Color(0xFFFADEBC) -val replyDarkTertiary = Color(0xFFB8CEA2) -val replyDarkOnTertiary = Color(0xFF243516) -val replyDarkTertiaryContainer = Color(0xFF3A4C2B) -val replyDarkOnTertiaryContainer = Color(0xFFD3EABC) -val replyDarkError = Color(0xFFFFB4A9) -val replyDarkErrorContainer = Color(0xFF930006) -val replyDarkOnError = Color(0xFF680003) -val replyDarkOnErrorContainer = Color(0xFFFFDAD4) -val replyDarkBackground = Color(0xFF1F1B16) -val replyDarkOnBackground = Color(0xFFEAE1D9) -val replyDarkSurface = Color(0xFF1F1B16) -val replyDarkOnSurface = Color(0xFFEAE1D9) -val replyDarkSurfaceVariant = Color(0xFF4F4539) -val replyDarkOnSurfaceVariant = Color(0xFFD3C4B4) -val replyDarkOutline = Color(0xFF9C8F80) -val replyDarkInverseOnSurface = Color(0xFF32281A) -val replyDarkInverseSurface = Color(0xFFEAE1D9) -val replyDarkPrimaryInverse = Color(0xFF624000) diff --git a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt index 209cbeb065..365eca54cc 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt @@ -15,95 +15,334 @@ */ package com.example.reply.ui.theme - +import android.app.Activity +import android.app.UiModeManager +import android.content.Context import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.lightColorScheme import androidx.compose.material3.darkColorScheme import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme -import androidx.compose.material3.lightColorScheme +import androidx.compose.material3.Typography import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat +import com.example.reply.ui.theme.replyTypography + +private val lightScheme = lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, +) + +private val darkScheme = darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, +) + +private val mediumContrastLightColorScheme = lightColorScheme( + primary = primaryLightMediumContrast, + onPrimary = onPrimaryLightMediumContrast, + primaryContainer = primaryContainerLightMediumContrast, + onPrimaryContainer = onPrimaryContainerLightMediumContrast, + secondary = secondaryLightMediumContrast, + onSecondary = onSecondaryLightMediumContrast, + secondaryContainer = secondaryContainerLightMediumContrast, + onSecondaryContainer = onSecondaryContainerLightMediumContrast, + tertiary = tertiaryLightMediumContrast, + onTertiary = onTertiaryLightMediumContrast, + tertiaryContainer = tertiaryContainerLightMediumContrast, + onTertiaryContainer = onTertiaryContainerLightMediumContrast, + error = errorLightMediumContrast, + onError = onErrorLightMediumContrast, + errorContainer = errorContainerLightMediumContrast, + onErrorContainer = onErrorContainerLightMediumContrast, + background = backgroundLightMediumContrast, + onBackground = onBackgroundLightMediumContrast, + surface = surfaceLightMediumContrast, + onSurface = onSurfaceLightMediumContrast, + surfaceVariant = surfaceVariantLightMediumContrast, + onSurfaceVariant = onSurfaceVariantLightMediumContrast, + outline = outlineLightMediumContrast, + outlineVariant = outlineVariantLightMediumContrast, + scrim = scrimLightMediumContrast, + inverseSurface = inverseSurfaceLightMediumContrast, + inverseOnSurface = inverseOnSurfaceLightMediumContrast, + inversePrimary = inversePrimaryLightMediumContrast, + surfaceDim = surfaceDimLightMediumContrast, + surfaceBright = surfaceBrightLightMediumContrast, + surfaceContainerLowest = surfaceContainerLowestLightMediumContrast, + surfaceContainerLow = surfaceContainerLowLightMediumContrast, + surfaceContainer = surfaceContainerLightMediumContrast, + surfaceContainerHigh = surfaceContainerHighLightMediumContrast, + surfaceContainerHighest = surfaceContainerHighestLightMediumContrast, +) + +private val highContrastLightColorScheme = lightColorScheme( + primary = primaryLightHighContrast, + onPrimary = onPrimaryLightHighContrast, + primaryContainer = primaryContainerLightHighContrast, + onPrimaryContainer = onPrimaryContainerLightHighContrast, + secondary = secondaryLightHighContrast, + onSecondary = onSecondaryLightHighContrast, + secondaryContainer = secondaryContainerLightHighContrast, + onSecondaryContainer = onSecondaryContainerLightHighContrast, + tertiary = tertiaryLightHighContrast, + onTertiary = onTertiaryLightHighContrast, + tertiaryContainer = tertiaryContainerLightHighContrast, + onTertiaryContainer = onTertiaryContainerLightHighContrast, + error = errorLightHighContrast, + onError = onErrorLightHighContrast, + errorContainer = errorContainerLightHighContrast, + onErrorContainer = onErrorContainerLightHighContrast, + background = backgroundLightHighContrast, + onBackground = onBackgroundLightHighContrast, + surface = surfaceLightHighContrast, + onSurface = onSurfaceLightHighContrast, + surfaceVariant = surfaceVariantLightHighContrast, + onSurfaceVariant = onSurfaceVariantLightHighContrast, + outline = outlineLightHighContrast, + outlineVariant = outlineVariantLightHighContrast, + scrim = scrimLightHighContrast, + inverseSurface = inverseSurfaceLightHighContrast, + inverseOnSurface = inverseOnSurfaceLightHighContrast, + inversePrimary = inversePrimaryLightHighContrast, + surfaceDim = surfaceDimLightHighContrast, + surfaceBright = surfaceBrightLightHighContrast, + surfaceContainerLowest = surfaceContainerLowestLightHighContrast, + surfaceContainerLow = surfaceContainerLowLightHighContrast, + surfaceContainer = surfaceContainerLightHighContrast, + surfaceContainerHigh = surfaceContainerHighLightHighContrast, + surfaceContainerHighest = surfaceContainerHighestLightHighContrast, +) -// Material 3 color schemes -private val replyDarkColorScheme = darkColorScheme( - primary = replyDarkPrimary, - onPrimary = replyDarkOnPrimary, - primaryContainer = replyDarkPrimaryContainer, - onPrimaryContainer = replyDarkOnPrimaryContainer, - inversePrimary = replyDarkPrimaryInverse, - secondary = replyDarkSecondary, - onSecondary = replyDarkOnSecondary, - secondaryContainer = replyDarkSecondaryContainer, - onSecondaryContainer = replyDarkOnSecondaryContainer, - tertiary = replyDarkTertiary, - onTertiary = replyDarkOnTertiary, - tertiaryContainer = replyDarkTertiaryContainer, - onTertiaryContainer = replyDarkOnTertiaryContainer, - error = replyDarkError, - onError = replyDarkOnError, - errorContainer = replyDarkErrorContainer, - onErrorContainer = replyDarkOnErrorContainer, - background = replyDarkBackground, - onBackground = replyDarkOnBackground, - surface = replyDarkSurface, - onSurface = replyDarkOnSurface, - inverseSurface = replyDarkInverseSurface, - inverseOnSurface = replyDarkInverseOnSurface, - surfaceVariant = replyDarkSurfaceVariant, - onSurfaceVariant = replyDarkOnSurfaceVariant, - outline = replyDarkOutline +private val mediumContrastDarkColorScheme = darkColorScheme( + primary = primaryDarkMediumContrast, + onPrimary = onPrimaryDarkMediumContrast, + primaryContainer = primaryContainerDarkMediumContrast, + onPrimaryContainer = onPrimaryContainerDarkMediumContrast, + secondary = secondaryDarkMediumContrast, + onSecondary = onSecondaryDarkMediumContrast, + secondaryContainer = secondaryContainerDarkMediumContrast, + onSecondaryContainer = onSecondaryContainerDarkMediumContrast, + tertiary = tertiaryDarkMediumContrast, + onTertiary = onTertiaryDarkMediumContrast, + tertiaryContainer = tertiaryContainerDarkMediumContrast, + onTertiaryContainer = onTertiaryContainerDarkMediumContrast, + error = errorDarkMediumContrast, + onError = onErrorDarkMediumContrast, + errorContainer = errorContainerDarkMediumContrast, + onErrorContainer = onErrorContainerDarkMediumContrast, + background = backgroundDarkMediumContrast, + onBackground = onBackgroundDarkMediumContrast, + surface = surfaceDarkMediumContrast, + onSurface = onSurfaceDarkMediumContrast, + surfaceVariant = surfaceVariantDarkMediumContrast, + onSurfaceVariant = onSurfaceVariantDarkMediumContrast, + outline = outlineDarkMediumContrast, + outlineVariant = outlineVariantDarkMediumContrast, + scrim = scrimDarkMediumContrast, + inverseSurface = inverseSurfaceDarkMediumContrast, + inverseOnSurface = inverseOnSurfaceDarkMediumContrast, + inversePrimary = inversePrimaryDarkMediumContrast, + surfaceDim = surfaceDimDarkMediumContrast, + surfaceBright = surfaceBrightDarkMediumContrast, + surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast, + surfaceContainerLow = surfaceContainerLowDarkMediumContrast, + surfaceContainer = surfaceContainerDarkMediumContrast, + surfaceContainerHigh = surfaceContainerHighDarkMediumContrast, + surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast, ) -private val replyLightColorScheme = lightColorScheme( - primary = replyLightPrimary, - onPrimary = replyLightOnPrimary, - primaryContainer = replyLightPrimaryContainer, - onPrimaryContainer = replyLightOnPrimaryContainer, - inversePrimary = replyLightPrimaryInverse, - secondary = replyLightSecondary, - onSecondary = replyLightOnSecondary, - secondaryContainer = replyLightSecondaryContainer, - onSecondaryContainer = replyLightOnSecondaryContainer, - tertiary = replyLightTertiary, - onTertiary = replyLightOnTertiary, - tertiaryContainer = replyLightTertiaryContainer, - onTertiaryContainer = replyLightOnTertiaryContainer, - error = replyLightError, - onError = replyLightOnError, - errorContainer = replyLightErrorContainer, - onErrorContainer = replyLightOnErrorContainer, - background = replyLightBackground, - onBackground = replyLightOnBackground, - surface = replyLightSurface, - onSurface = replyLightOnSurface, - inverseSurface = replyLightInverseSurface, - inverseOnSurface = replyLightInverseOnSurface, - surfaceVariant = replyLightSurfaceVariant, - onSurfaceVariant = replyLightOnSurfaceVariant, - outline = replyLightOutline +private val highContrastDarkColorScheme = darkColorScheme( + primary = primaryDarkHighContrast, + onPrimary = onPrimaryDarkHighContrast, + primaryContainer = primaryContainerDarkHighContrast, + onPrimaryContainer = onPrimaryContainerDarkHighContrast, + secondary = secondaryDarkHighContrast, + onSecondary = onSecondaryDarkHighContrast, + secondaryContainer = secondaryContainerDarkHighContrast, + onSecondaryContainer = onSecondaryContainerDarkHighContrast, + tertiary = tertiaryDarkHighContrast, + onTertiary = onTertiaryDarkHighContrast, + tertiaryContainer = tertiaryContainerDarkHighContrast, + onTertiaryContainer = onTertiaryContainerDarkHighContrast, + error = errorDarkHighContrast, + onError = onErrorDarkHighContrast, + errorContainer = errorContainerDarkHighContrast, + onErrorContainer = onErrorContainerDarkHighContrast, + background = backgroundDarkHighContrast, + onBackground = onBackgroundDarkHighContrast, + surface = surfaceDarkHighContrast, + onSurface = onSurfaceDarkHighContrast, + surfaceVariant = surfaceVariantDarkHighContrast, + onSurfaceVariant = onSurfaceVariantDarkHighContrast, + outline = outlineDarkHighContrast, + outlineVariant = outlineVariantDarkHighContrast, + scrim = scrimDarkHighContrast, + inverseSurface = inverseSurfaceDarkHighContrast, + inverseOnSurface = inverseOnSurfaceDarkHighContrast, + inversePrimary = inversePrimaryDarkHighContrast, + surfaceDim = surfaceDimDarkHighContrast, + surfaceBright = surfaceBrightDarkHighContrast, + surfaceContainerLowest = surfaceContainerLowestDarkHighContrast, + surfaceContainerLow = surfaceContainerLowDarkHighContrast, + surfaceContainer = surfaceContainerDarkHighContrast, + surfaceContainerHigh = surfaceContainerHighDarkHighContrast, + surfaceContainerHighest = surfaceContainerHighestDarkHighContrast, ) +fun isContrastAvailable(): Boolean { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE; +} + @Composable -fun ReplyTheme( +fun selectSchemeForContrast(isDark: Boolean, ) : ColorScheme { + val context = LocalContext.current + val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager; + val contrastLevel = if (!isContrastAvailable()) 0.0 else uiModeManager.contrast + + val colorScheme = when(contrastLevel as Float) { + in 0.0f .. 0.33f -> if (isDark) darkScheme else lightScheme + in 0.34f..0.66f -> if (isDark) mediumContrastDarkColorScheme else mediumContrastLightColorScheme + in 0.67f..1.0f -> if (isDark) highContrastDarkColorScheme else highContrastLightColorScheme + else -> if (isDark) darkScheme else lightScheme + } + return colorScheme +} +@Composable +fun ContrastAwareReplyTheme( darkTheme: Boolean = isSystemInDarkTheme(), - dynamicColor: Boolean = true, - content: @Composable () -> Unit + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = false, + content: @Composable() () -> Unit ) { val replyColorScheme = when { dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { val context = LocalContext.current if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) } - darkTheme -> replyDarkColorScheme - else -> replyLightColorScheme + + else -> selectSchemeForContrast(darkTheme) + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = replyColorScheme.primary.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + } } MaterialTheme( colorScheme = replyColorScheme, typography = replyTypography, - shapes = shapes, content = content ) } + +@Composable +fun ReplyTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable() () -> Unit +) { + val replyColorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> darkScheme + else -> lightScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = replyColorScheme.primary.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + } + } + + MaterialTheme( + colorScheme = replyColorScheme, + typography = replyTypography, + content = content + ) +} + From b0e963791f733f67f48799e4ddcf3083968bbf28 Mon Sep 17 00:00:00 2001 From: James Williams <66931+jwill@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:43:45 -0700 Subject: [PATCH 2/8] [Reply] Whitespaces and shapes --- .../src/main/java/com/example/reply/ui/theme/Color.kt | 9 +-------- .../src/main/java/com/example/reply/ui/theme/Theme.kt | 4 ++-- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt b/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt index 3bb6f7e5a7..79f1f10080 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt @@ -234,11 +234,4 @@ val surfaceContainerLowestDarkHighContrast = Color(0xFF120D07) val surfaceContainerLowDarkHighContrast = Color(0xFF201B13) val surfaceContainerDarkHighContrast = Color(0xFF251F17) val surfaceContainerHighDarkHighContrast = Color(0xFF2F2921) -val surfaceContainerHighestDarkHighContrast = Color(0xFF3B342B) - - - - - - - +val surfaceContainerHighestDarkHighContrast = Color(0xFF3B342B) \ No newline at end of file diff --git a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt index 365eca54cc..f41d4bc132 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt @@ -309,7 +309,7 @@ fun ContrastAwareReplyTheme( MaterialTheme( colorScheme = replyColorScheme, - typography = replyTypography, + typography = replyTypography, shapes = shapes, content = content ) } @@ -341,7 +341,7 @@ fun ReplyTheme( MaterialTheme( colorScheme = replyColorScheme, - typography = replyTypography, + typography = replyTypography, shapes = shapes, content = content ) } From 041b8157df2e275b7e3ec7c8991aabd205b2d959 Mon Sep 17 00:00:00 2001 From: James Williams <66931+jwill@users.noreply.github.com> Date: Fri, 15 Mar 2024 12:08:53 -0700 Subject: [PATCH 3/8] Update ReplyEmailThreadItem.kt Code formatting. --- .../com/example/reply/ui/components/ReplyEmailThreadItem.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt index 99a4faba76..5ddfe31627 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt @@ -53,7 +53,8 @@ fun ReplyEmailThreadItem( ) { Card( modifier = modifier.padding(horizontal = 16.dp, vertical = 4.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceContainerHigh) + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainerHigh) ) { Column( modifier = Modifier From 67361868cf02ca6e8b8f78008504850fd598ebc1 Mon Sep 17 00:00:00 2001 From: James Williams <66931+jwill@users.noreply.github.com> Date: Fri, 15 Mar 2024 12:14:35 -0700 Subject: [PATCH 4/8] Update Theme.kt Formatting. --- .../src/main/java/com/example/reply/ui/theme/Theme.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt index f41d4bc132..c3904e5c80 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt @@ -276,9 +276,12 @@ fun selectSchemeForContrast(isDark: Boolean, ) : ColorScheme { val contrastLevel = if (!isContrastAvailable()) 0.0 else uiModeManager.contrast val colorScheme = when(contrastLevel as Float) { - in 0.0f .. 0.33f -> if (isDark) darkScheme else lightScheme - in 0.34f..0.66f -> if (isDark) mediumContrastDarkColorScheme else mediumContrastLightColorScheme - in 0.67f..1.0f -> if (isDark) highContrastDarkColorScheme else highContrastLightColorScheme + in 0.0f .. 0.33f -> if (isDark) + darkScheme else lightScheme + in 0.34f..0.66f -> if (isDark) + mediumContrastDarkColorScheme else mediumContrastLightColorScheme + in 0.67f..1.0f -> if (isDark) + highContrastDarkColorScheme else highContrastLightColorScheme else -> if (isDark) darkScheme else lightScheme } return colorScheme From fcce31eed2ab2501723c1d3b6f1225c6576e63a2 Mon Sep 17 00:00:00 2001 From: jwill Date: Fri, 15 Mar 2024 19:16:53 +0000 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=A4=96=20Apply=20Spotless?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/components/ReplyEmailThreadItem.kt | 4 +- .../java/com/example/reply/ui/theme/Color.kt | 2 +- .../java/com/example/reply/ui/theme/Theme.kt | 59 +++++++++---------- 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt index 5ddfe31627..d3a867f4c7 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt @@ -36,7 +36,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text -import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -54,7 +53,8 @@ fun ReplyEmailThreadItem( Card( modifier = modifier.padding(horizontal = 16.dp, vertical = 4.dp), colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceContainerHigh) + containerColor = MaterialTheme.colorScheme.surfaceContainerHigh + ) ) { Column( modifier = Modifier diff --git a/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt b/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt index 79f1f10080..e6c03db06b 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/theme/Color.kt @@ -234,4 +234,4 @@ val surfaceContainerLowestDarkHighContrast = Color(0xFF120D07) val surfaceContainerLowDarkHighContrast = Color(0xFF201B13) val surfaceContainerDarkHighContrast = Color(0xFF251F17) val surfaceContainerHighDarkHighContrast = Color(0xFF2F2921) -val surfaceContainerHighestDarkHighContrast = Color(0xFF3B342B) \ No newline at end of file +val surfaceContainerHighestDarkHighContrast = Color(0xFF3B342B) diff --git a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt index c3904e5c80..d041e8df73 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt @@ -22,20 +22,16 @@ import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.lightColorScheme import androidx.compose.material3.darkColorScheme import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme -import androidx.compose.material3.Typography +import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.Immutable import androidx.compose.runtime.SideEffect -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat -import com.example.reply.ui.theme.replyTypography private val lightScheme = lightColorScheme( primary = primaryLight, @@ -266,17 +262,17 @@ private val highContrastDarkColorScheme = darkColorScheme( ) fun isContrastAvailable(): Boolean { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE; + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE } @Composable -fun selectSchemeForContrast(isDark: Boolean, ) : ColorScheme { +fun selectSchemeForContrast(isDark: Boolean,): ColorScheme { val context = LocalContext.current - val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager; + val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager val contrastLevel = if (!isContrastAvailable()) 0.0 else uiModeManager.contrast - val colorScheme = when(contrastLevel as Float) { - in 0.0f .. 0.33f -> if (isDark) + val colorScheme = when (contrastLevel as Float) { + in 0.0f..0.33f -> if (isDark) darkScheme else lightScheme in 0.34f..0.66f -> if (isDark) mediumContrastDarkColorScheme else mediumContrastLightColorScheme @@ -324,28 +320,27 @@ fun ReplyTheme( dynamicColor: Boolean = true, content: @Composable() () -> Unit ) { - val replyColorScheme = when { - dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { - val context = LocalContext.current - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) - } - - darkTheme -> darkScheme - else -> lightScheme - } - val view = LocalView.current - if (!view.isInEditMode) { - SideEffect { - val window = (view.context as Activity).window - window.statusBarColor = replyColorScheme.primary.toArgb() - WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + val replyColorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> darkScheme + else -> lightScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = replyColorScheme.primary.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + } } - } - MaterialTheme( - colorScheme = replyColorScheme, - typography = replyTypography, shapes = shapes, - content = content - ) + MaterialTheme( + colorScheme = replyColorScheme, + typography = replyTypography, shapes = shapes, + content = content + ) } - From 84a8e6bd5a252fb9f59002e404e0dac620194710 Mon Sep 17 00:00:00 2001 From: James Williams <66931+jwill@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:01:56 -0700 Subject: [PATCH 6/8] Addressed code review feedback. Removed partially used theme and implemented code style suggestions. Modified selectSchemeForContrast function to allow it to pass through on API versions without contrast support. --- .../java/com/example/reply/ui/MainActivity.kt | 11 ++- .../ui/components/ReplyEmailThreadItem.kt | 3 +- .../java/com/example/reply/ui/theme/Theme.kt | 67 ++++++------------- 3 files changed, 27 insertions(+), 54 deletions(-) diff --git a/Reply/app/src/main/java/com/example/reply/ui/MainActivity.kt b/Reply/app/src/main/java/com/example/reply/ui/MainActivity.kt index 83e8a471e8..c3cd2e5709 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/MainActivity.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/MainActivity.kt @@ -32,7 +32,6 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.example.reply.data.local.LocalEmailsDataProvider import com.example.reply.ui.theme.ContrastAwareReplyTheme -import com.example.reply.ui.theme.ReplyTheme import com.google.accompanist.adaptive.calculateDisplayFeatures class MainActivity : ComponentActivity() { @@ -73,7 +72,7 @@ class MainActivity : ComponentActivity() { @Preview(showBackground = true) @Composable fun ReplyAppPreview() { - ReplyTheme { + ContrastAwareReplyTheme { ReplyApp( replyHomeUIState = ReplyHomeUIState(emails = LocalEmailsDataProvider.allEmails), windowSize = WindowSizeClass.calculateFromSize(DpSize(400.dp, 900.dp)), @@ -86,7 +85,7 @@ fun ReplyAppPreview() { @Preview(showBackground = true, widthDp = 700, heightDp = 500) @Composable fun ReplyAppPreviewTablet() { - ReplyTheme { + ContrastAwareReplyTheme { ReplyApp( replyHomeUIState = ReplyHomeUIState(emails = LocalEmailsDataProvider.allEmails), windowSize = WindowSizeClass.calculateFromSize(DpSize(700.dp, 500.dp)), @@ -99,7 +98,7 @@ fun ReplyAppPreviewTablet() { @Preview(showBackground = true, widthDp = 500, heightDp = 700) @Composable fun ReplyAppPreviewTabletPortrait() { - ReplyTheme { + ContrastAwareReplyTheme { ReplyApp( replyHomeUIState = ReplyHomeUIState(emails = LocalEmailsDataProvider.allEmails), windowSize = WindowSizeClass.calculateFromSize(DpSize(500.dp, 700.dp)), @@ -112,7 +111,7 @@ fun ReplyAppPreviewTabletPortrait() { @Preview(showBackground = true, widthDp = 1100, heightDp = 600) @Composable fun ReplyAppPreviewDesktop() { - ReplyTheme { + ContrastAwareReplyTheme { ReplyApp( replyHomeUIState = ReplyHomeUIState(emails = LocalEmailsDataProvider.allEmails), windowSize = WindowSizeClass.calculateFromSize(DpSize(1100.dp, 600.dp)), @@ -125,7 +124,7 @@ fun ReplyAppPreviewDesktop() { @Preview(showBackground = true, widthDp = 600, heightDp = 1100) @Composable fun ReplyAppPreviewDesktopPortrait() { - ReplyTheme { + ContrastAwareReplyTheme { ReplyApp( replyHomeUIState = ReplyHomeUIState(emails = LocalEmailsDataProvider.allEmails), windowSize = WindowSizeClass.calculateFromSize(DpSize(600.dp, 1100.dp)), diff --git a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt index d3a867f4c7..d7c6c1b2d2 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt @@ -112,7 +112,7 @@ fun ReplyEmailThreadItem( modifier = Modifier .fillMaxWidth() .padding(top = 20.dp, bottom = 8.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), ) { Button( onClick = { /*TODO*/ }, @@ -126,7 +126,6 @@ fun ReplyEmailThreadItem( color = MaterialTheme.colorScheme.onSurface ) } - Spacer(modifier = Modifier.width(8.dp)) Button( onClick = { /*TODO*/ }, modifier = Modifier.weight(1f), diff --git a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt index d041e8df73..c5c644d4a5 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt @@ -268,19 +268,25 @@ fun isContrastAvailable(): Boolean { @Composable fun selectSchemeForContrast(isDark: Boolean,): ColorScheme { val context = LocalContext.current - val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager - val contrastLevel = if (!isContrastAvailable()) 0.0 else uiModeManager.contrast + var colorScheme = if (isDark) darkScheme else lightScheme + if (isContrastAvailable()) { + val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager; + val contrastLevel = uiModeManager.contrast - val colorScheme = when (contrastLevel as Float) { - in 0.0f..0.33f -> if (isDark) - darkScheme else lightScheme - in 0.34f..0.66f -> if (isDark) - mediumContrastDarkColorScheme else mediumContrastLightColorScheme - in 0.67f..1.0f -> if (isDark) - highContrastDarkColorScheme else highContrastLightColorScheme - else -> if (isDark) darkScheme else lightScheme - } - return colorScheme + colorScheme = when (contrastLevel) { + in 0.0f..0.33f -> if (isDark) + darkScheme else lightScheme + + in 0.34f..0.66f -> if (isDark) + mediumContrastDarkColorScheme else mediumContrastLightColorScheme + + in 0.67f..1.0f -> if (isDark) + highContrastDarkColorScheme else highContrastLightColorScheme + + else -> if (isDark) darkScheme else lightScheme + } + return colorScheme + } else return colorScheme } @Composable fun ContrastAwareReplyTheme( @@ -308,39 +314,8 @@ fun ContrastAwareReplyTheme( MaterialTheme( colorScheme = replyColorScheme, - typography = replyTypography, shapes = shapes, + typography = replyTypography, + shapes = shapes, content = content ) -} - -@Composable -fun ReplyTheme( - darkTheme: Boolean = isSystemInDarkTheme(), - // Dynamic color is available on Android 12+ - dynamicColor: Boolean = true, - content: @Composable() () -> Unit -) { - val replyColorScheme = when { - dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { - val context = LocalContext.current - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) - } - - darkTheme -> darkScheme - else -> lightScheme - } - val view = LocalView.current - if (!view.isInEditMode) { - SideEffect { - val window = (view.context as Activity).window - window.statusBarColor = replyColorScheme.primary.toArgb() - WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme - } - } - - MaterialTheme( - colorScheme = replyColorScheme, - typography = replyTypography, shapes = shapes, - content = content - ) -} +} \ No newline at end of file From 5f917a7d34394eccb2edf92f68eca8c7fd00b21e Mon Sep 17 00:00:00 2001 From: jwill Date: Wed, 27 Mar 2024 17:04:24 +0000 Subject: [PATCH 7/8] =?UTF-8?q?=F0=9F=A4=96=20Apply=20Spotless?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/reply/ui/components/ReplyEmailThreadItem.kt | 2 -- Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt index d7c6c1b2d2..b4ca1b1cb1 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/components/ReplyEmailThreadItem.kt @@ -20,10 +20,8 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column 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.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.StarBorder diff --git a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt index c5c644d4a5..c4f90403b7 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt @@ -270,7 +270,7 @@ fun selectSchemeForContrast(isDark: Boolean,): ColorScheme { val context = LocalContext.current var colorScheme = if (isDark) darkScheme else lightScheme if (isContrastAvailable()) { - val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager; + val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager val contrastLevel = uiModeManager.contrast colorScheme = when (contrastLevel) { @@ -318,4 +318,4 @@ fun ContrastAwareReplyTheme( shapes = shapes, content = content ) -} \ No newline at end of file +} From b6352d4c0f93eba6f702de6b8f7c2cb5dd5a702d Mon Sep 17 00:00:00 2001 From: James Williams <66931+jwill@users.noreply.github.com> Date: Wed, 27 Mar 2024 11:05:36 -0700 Subject: [PATCH 8/8] Update Theme.kt --- Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt index c5c644d4a5..f7a6dfd852 100644 --- a/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt +++ b/Reply/app/src/main/java/com/example/reply/ui/theme/Theme.kt @@ -270,7 +270,7 @@ fun selectSchemeForContrast(isDark: Boolean,): ColorScheme { val context = LocalContext.current var colorScheme = if (isDark) darkScheme else lightScheme if (isContrastAvailable()) { - val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager; + val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager val contrastLevel = uiModeManager.contrast colorScheme = when (contrastLevel) {