ios widget showing what is available at chucks
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: use material theme properly

+166 -237
+15 -10
android/app/src/main/java/com/wasupchucks/ui/components/AllergenBadge.kt
··· 3 3 import androidx.compose.foundation.layout.Arrangement 4 4 import androidx.compose.foundation.layout.Row 5 5 import androidx.compose.foundation.layout.padding 6 - import androidx.compose.foundation.shape.RoundedCornerShape 6 + import androidx.compose.material3.MaterialTheme 7 7 import androidx.compose.material3.Surface 8 8 import androidx.compose.material3.Text 9 9 import androidx.compose.runtime.Composable ··· 16 16 import androidx.compose.ui.unit.sp 17 17 import com.wasupchucks.R 18 18 import com.wasupchucks.data.model.Allergen 19 - import com.wasupchucks.ui.theme.AllergenDietary 20 - import com.wasupchucks.ui.theme.AllergenDietaryContainer 21 - import com.wasupchucks.ui.theme.AllergenWarning 22 - import com.wasupchucks.ui.theme.AllergenWarningContainer 23 19 24 20 @Composable 25 21 fun AllergenBadge( 26 22 allergen: Allergen, 27 23 modifier: Modifier = Modifier 28 24 ) { 29 - val backgroundColor = if (allergen.isDietary) AllergenDietaryContainer else AllergenWarningContainer 30 - val textColor = if (allergen.isDietary) AllergenDietary else AllergenWarning 25 + // Dietary badges use primary colors, warning badges use tertiary 26 + val backgroundColor = if (allergen.isDietary) { 27 + MaterialTheme.colorScheme.primaryContainer 28 + } else { 29 + MaterialTheme.colorScheme.tertiaryContainer 30 + } 31 + val textColor = if (allergen.isDietary) { 32 + MaterialTheme.colorScheme.onPrimaryContainer 33 + } else { 34 + MaterialTheme.colorScheme.onTertiaryContainer 35 + } 31 36 32 37 Surface( 33 38 modifier = modifier, 34 - shape = RoundedCornerShape(4.dp), 39 + shape = MaterialTheme.shapes.extraSmall, 35 40 color = backgroundColor 36 41 ) { 37 42 Text( 38 43 text = allergen.symbol, 39 - fontSize = 9.sp, 44 + fontSize = 10.sp, 40 45 fontWeight = FontWeight.Bold, 41 46 color = textColor, 42 - modifier = Modifier.padding(horizontal = 5.dp, vertical = 3.dp) 47 + modifier = Modifier.padding(horizontal = 6.dp, vertical = 4.dp) 43 48 ) 44 49 } 45 50 }
+18 -19
android/app/src/main/java/com/wasupchucks/ui/components/ErrorCard.kt
··· 10 10 import androidx.compose.material.icons.Icons 11 11 import androidx.compose.material.icons.filled.WifiOff 12 12 import androidx.compose.material3.Button 13 - import androidx.compose.material3.ButtonDefaults 14 - import androidx.compose.material3.ElevatedCard 13 + import androidx.compose.material3.Card 14 + import androidx.compose.material3.CardDefaults 15 15 import androidx.compose.material3.Icon 16 16 import androidx.compose.material3.MaterialTheme 17 17 import androidx.compose.material3.Text ··· 23 23 import androidx.compose.ui.unit.dp 24 24 import com.wasupchucks.R 25 25 import com.wasupchucks.data.repository.ChucksError 26 - import com.wasupchucks.ui.theme.StatusClosed 27 26 28 27 @Composable 29 28 fun ErrorCard( ··· 38 37 else -> stringResource(R.string.error_generic) 39 38 } 40 39 41 - ElevatedCard( 42 - modifier = modifier.fillMaxWidth() 40 + Card( 41 + modifier = modifier.fillMaxWidth(), 42 + colors = CardDefaults.cardColors( 43 + containerColor = MaterialTheme.colorScheme.errorContainer 44 + ), 45 + shape = MaterialTheme.shapes.large 43 46 ) { 44 47 Column( 45 48 modifier = Modifier 46 49 .fillMaxWidth() 47 - .padding(24.dp), 50 + .padding(32.dp), 48 51 horizontalAlignment = Alignment.CenterHorizontally, 49 52 verticalArrangement = Arrangement.Center 50 53 ) { 51 54 Icon( 52 55 imageVector = Icons.Filled.WifiOff, 53 56 contentDescription = null, 54 - modifier = Modifier.size(40.dp), 55 - tint = MaterialTheme.colorScheme.onSurfaceVariant 57 + modifier = Modifier.size(48.dp), 58 + tint = MaterialTheme.colorScheme.onErrorContainer 56 59 ) 57 60 58 - Spacer(modifier = Modifier.height(16.dp)) 61 + Spacer(modifier = Modifier.height(20.dp)) 59 62 60 63 Text( 61 64 text = stringResource(R.string.error_title), 62 - style = MaterialTheme.typography.titleMedium 65 + style = MaterialTheme.typography.titleLarge, 66 + color = MaterialTheme.colorScheme.onErrorContainer 63 67 ) 64 68 65 69 Spacer(modifier = Modifier.height(8.dp)) 66 70 67 71 Text( 68 72 text = errorMessage, 69 - style = MaterialTheme.typography.bodyMedium, 70 - color = MaterialTheme.colorScheme.onSurfaceVariant, 73 + style = MaterialTheme.typography.bodyLarge, 74 + color = MaterialTheme.colorScheme.onErrorContainer.copy(alpha = 0.8f), 71 75 textAlign = TextAlign.Center 72 76 ) 73 77 74 - Spacer(modifier = Modifier.height(16.dp)) 78 + Spacer(modifier = Modifier.height(24.dp)) 75 79 76 - Button( 77 - onClick = onRetry, 78 - colors = ButtonDefaults.buttonColors( 79 - containerColor = StatusClosed 80 - ) 81 - ) { 80 + Button(onClick = onRetry) { 82 81 Text(text = stringResource(R.string.try_again)) 83 82 } 84 83 }
+14 -11
android/app/src/main/java/com/wasupchucks/ui/components/MealDetailSheet.kt
··· 49 49 ModalBottomSheet( 50 50 onDismissRequest = onDismiss, 51 51 sheetState = sheetState, 52 - modifier = modifier 52 + modifier = modifier, 53 + containerColor = MaterialTheme.colorScheme.surface 53 54 ) { 54 55 Column( 55 56 modifier = Modifier 56 57 .fillMaxWidth() 57 - .padding(horizontal = 16.dp) 58 + .padding(horizontal = 24.dp) 58 59 ) { 59 60 // Header 60 61 Row( ··· 64 65 ) { 65 66 Text( 66 67 text = meal.phase.displayName, 67 - style = MaterialTheme.typography.headlineSmall, 68 - fontWeight = FontWeight.Bold 68 + style = MaterialTheme.typography.headlineMedium, 69 + fontWeight = FontWeight.Bold, 70 + color = MaterialTheme.colorScheme.onSurface 69 71 ) 70 72 IconButton(onClick = onDismiss) { 71 73 Icon( 72 74 imageVector = Icons.Filled.Close, 73 - contentDescription = "Close" 75 + contentDescription = "Close", 76 + tint = MaterialTheme.colorScheme.onSurfaceVariant 74 77 ) 75 78 } 76 79 } 77 80 78 - Spacer(modifier = Modifier.height(8.dp)) 81 + Spacer(modifier = Modifier.height(16.dp)) 79 82 80 83 if (venues.isEmpty()) { 81 84 // Empty state ··· 113 116 venues.forEach { venue -> 114 117 item(key = "header-${venue.id}") { 115 118 if (venues.indexOf(venue) > 0) { 116 - HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp)) 119 + HorizontalDivider(modifier = Modifier.padding(vertical = 12.dp)) 117 120 } 118 121 Text( 119 122 text = venue.venue, 120 - style = MaterialTheme.typography.titleSmall, 123 + style = MaterialTheme.typography.titleMedium, 121 124 fontWeight = FontWeight.SemiBold, 122 125 color = MaterialTheme.colorScheme.primary, 123 126 modifier = Modifier.padding(top = 8.dp) ··· 128 131 Row( 129 132 modifier = Modifier 130 133 .fillMaxWidth() 131 - .padding(vertical = 4.dp), 132 - horizontalArrangement = Arrangement.SpaceBetween, 134 + .padding(vertical = 6.dp), 135 + horizontalArrangement = Arrangement.spacedBy(12.dp), 133 136 verticalAlignment = Alignment.CenterVertically 134 137 ) { 135 138 Text( 136 139 text = item.name, 137 - style = MaterialTheme.typography.bodyMedium, 140 + style = MaterialTheme.typography.bodyLarge, 138 141 modifier = Modifier.weight(1f) 139 142 ) 140 143 AllergenRow(allergens = item.allergens)
+21 -16
android/app/src/main/java/com/wasupchucks/ui/components/ScheduleCard.kt
··· 9 9 import androidx.compose.foundation.layout.fillMaxWidth 10 10 import androidx.compose.foundation.layout.height 11 11 import androidx.compose.foundation.layout.padding 12 - import androidx.compose.foundation.shape.RoundedCornerShape 13 - import androidx.compose.material3.ElevatedCard 12 + import androidx.compose.material3.Card 13 + import androidx.compose.material3.CardDefaults 14 14 import androidx.compose.material3.Icon 15 15 import androidx.compose.material3.MaterialTheme 16 16 import androidx.compose.material3.Surface ··· 27 27 import com.wasupchucks.R 28 28 import com.wasupchucks.data.model.ChucksStatus 29 29 import com.wasupchucks.data.model.MealSchedule 30 - import com.wasupchucks.ui.theme.StatusOpen 31 30 32 31 @Composable 33 32 fun ScheduleCard( ··· 36 35 onMealClick: (MealSchedule) -> Unit, 37 36 modifier: Modifier = Modifier 38 37 ) { 39 - ElevatedCard( 40 - modifier = modifier.fillMaxWidth() 38 + Card( 39 + modifier = modifier.fillMaxWidth(), 40 + colors = CardDefaults.cardColors( 41 + containerColor = MaterialTheme.colorScheme.surfaceContainerLow 42 + ), 43 + shape = MaterialTheme.shapes.large 41 44 ) { 42 45 Column( 43 46 modifier = Modifier 44 47 .fillMaxWidth() 45 - .padding(16.dp) 48 + .padding(20.dp) 46 49 ) { 47 50 Text( 48 51 text = stringResource(R.string.todays_schedule), 49 52 style = MaterialTheme.typography.titleMedium, 50 - fontWeight = FontWeight.SemiBold 53 + fontWeight = FontWeight.SemiBold, 54 + color = MaterialTheme.colorScheme.onSurface 51 55 ) 52 56 53 - Spacer(modifier = Modifier.height(12.dp)) 57 + Spacer(modifier = Modifier.height(16.dp)) 54 58 55 59 Row( 56 60 modifier = Modifier.fillMaxWidth(), 57 - horizontalArrangement = Arrangement.spacedBy(8.dp) 61 + horizontalArrangement = Arrangement.spacedBy(12.dp) 58 62 ) { 59 63 schedule.forEach { meal -> 60 64 val isCurrent = status.isOpen && status.currentPhase == meal.phase ··· 87 91 endTime 88 92 ) + if (isCurrent) ", ${stringResource(R.string.current_meal)}" else "" 89 93 90 - val shape = RoundedCornerShape(12.dp) 94 + val shape = MaterialTheme.shapes.medium 91 95 val backgroundColor = if (isCurrent) { 92 - StatusOpen.copy(alpha = 0.12f) 96 + MaterialTheme.colorScheme.primaryContainer 93 97 } else { 94 - MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f) 98 + MaterialTheme.colorScheme.surfaceContainerHigh 95 99 } 96 100 val contentColor = if (isCurrent) { 97 - StatusOpen 101 + MaterialTheme.colorScheme.onPrimaryContainer 98 102 } else { 99 103 MaterialTheme.colorScheme.onSurface 100 104 } 101 105 val border = if (isCurrent) { 102 - BorderStroke(2.dp, StatusOpen) 106 + BorderStroke(2.dp, MaterialTheme.colorScheme.primary) 103 107 } else { 104 108 null 105 109 } ··· 130 134 color = contentColor 131 135 ) 132 136 Text( 133 - text = "$startTime-$endTime", 137 + text = "$startTime–$endTime", 134 138 style = MaterialTheme.typography.labelSmall, 135 - color = if (isCurrent) contentColor.copy(alpha = 0.8f) else MaterialTheme.colorScheme.onSurfaceVariant 139 + color = contentColor.copy(alpha = 0.7f), 140 + maxLines = 1 136 141 ) 137 142 } 138 143 }
+27 -16
android/app/src/main/java/com/wasupchucks/ui/components/StatusCard.kt
··· 1 1 package com.wasupchucks.ui.components 2 2 3 3 import androidx.compose.animation.animateContentSize 4 + import androidx.compose.animation.core.Spring 5 + import androidx.compose.animation.core.spring 4 6 import androidx.compose.foundation.layout.Arrangement 5 7 import androidx.compose.foundation.layout.Column 6 8 import androidx.compose.foundation.layout.Row ··· 8 10 import androidx.compose.foundation.layout.fillMaxWidth 9 11 import androidx.compose.foundation.layout.height 10 12 import androidx.compose.foundation.layout.padding 11 - import androidx.compose.material3.ElevatedCard 13 + import androidx.compose.material3.Card 14 + import androidx.compose.material3.CardDefaults 12 15 import androidx.compose.material3.Icon 13 16 import androidx.compose.material3.MaterialTheme 14 17 import androidx.compose.material3.Text ··· 25 28 import com.wasupchucks.data.model.MealPhase 26 29 import com.wasupchucks.data.model.toExpandedCountdown 27 30 import com.wasupchucks.ui.theme.CountdownTypography 28 - import com.wasupchucks.ui.theme.StatusClosed 29 - import com.wasupchucks.ui.theme.StatusOpen 30 - 31 31 @Composable 32 32 fun StatusCard( 33 33 status: ChucksStatus, 34 34 modifier: Modifier = Modifier 35 35 ) { 36 - val statusColor = if (status.isOpen) StatusOpen else StatusClosed 36 + val colorScheme = MaterialTheme.colorScheme 37 + val statusColor = if (status.isOpen) colorScheme.primary else colorScheme.tertiary 38 + 37 39 val statusIcon = if (status.isOpen) { 38 40 status.currentPhase.icon 39 41 } else { ··· 56 58 stringResource(R.string.closed_next_meal, status.nextPhase?.displayName ?: "") 57 59 } 58 60 59 - ElevatedCard( 60 - modifier = modifier.fillMaxWidth() 61 + Card( 62 + modifier = modifier.fillMaxWidth(), 63 + colors = CardDefaults.cardColors( 64 + containerColor = colorScheme.surfaceContainerHigh 65 + ), 66 + shape = MaterialTheme.shapes.large 61 67 ) { 62 68 Column( 63 69 modifier = Modifier 64 70 .fillMaxWidth() 65 - .padding(16.dp) 66 - .animateContentSize() 71 + .padding(24.dp) 72 + .animateContentSize( 73 + animationSpec = spring( 74 + dampingRatio = Spring.DampingRatioLowBouncy, 75 + stiffness = Spring.StiffnessLow 76 + ) 77 + ) 67 78 ) { 68 79 Row( 69 80 modifier = Modifier 70 81 .fillMaxWidth() 71 82 .semantics { contentDescription = accessibilityLabel }, 72 83 verticalAlignment = Alignment.CenterVertically, 73 - horizontalArrangement = Arrangement.spacedBy(8.dp) 84 + horizontalArrangement = Arrangement.spacedBy(12.dp) 74 85 ) { 75 86 Icon( 76 87 imageVector = statusIcon, ··· 80 91 Column { 81 92 Text( 82 93 text = statusText, 83 - style = MaterialTheme.typography.titleSmall, 94 + style = MaterialTheme.typography.titleMedium, 84 95 fontWeight = FontWeight.SemiBold, 85 96 color = statusColor 86 97 ) 87 98 Text( 88 99 text = mealText, 89 - style = MaterialTheme.typography.bodySmall, 90 - color = MaterialTheme.colorScheme.onSurfaceVariant 100 + style = MaterialTheme.typography.bodyMedium, 101 + color = colorScheme.onSurfaceVariant 91 102 ) 92 103 } 93 104 } 94 105 95 106 status.timeRemaining?.let { remaining -> 96 - Spacer(modifier = Modifier.height(8.dp)) 107 + Spacer(modifier = Modifier.height(16.dp)) 97 108 98 109 Text( 99 110 text = remaining.toExpandedCountdown(), ··· 110 121 111 122 Text( 112 123 text = untilText, 113 - style = MaterialTheme.typography.bodyMedium, 114 - color = MaterialTheme.colorScheme.onSurfaceVariant, 124 + style = MaterialTheme.typography.bodyLarge, 125 + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f), 115 126 modifier = Modifier.align(Alignment.CenterHorizontally) 116 127 ) 117 128 }
+28 -18
android/app/src/main/java/com/wasupchucks/ui/components/VenueCard.kt
··· 1 1 package com.wasupchucks.ui.components 2 2 3 3 import androidx.compose.animation.AnimatedVisibility 4 + import androidx.compose.animation.core.Spring 5 + import androidx.compose.animation.core.spring 4 6 import androidx.compose.animation.expandVertically 5 7 import androidx.compose.animation.fadeIn 6 8 import androidx.compose.animation.fadeOut ··· 11 13 import androidx.compose.foundation.layout.Box 12 14 import androidx.compose.foundation.layout.Column 13 15 import androidx.compose.foundation.layout.Row 14 - import androidx.compose.foundation.layout.Spacer 15 16 import androidx.compose.foundation.layout.fillMaxWidth 16 - import androidx.compose.foundation.layout.height 17 17 import androidx.compose.foundation.layout.padding 18 18 import androidx.compose.foundation.layout.size 19 19 import androidx.compose.foundation.shape.CircleShape 20 - import androidx.compose.foundation.shape.RoundedCornerShape 21 20 import androidx.compose.material.icons.Icons 22 21 import androidx.compose.material.icons.filled.ExpandLess 23 22 import androidx.compose.material.icons.filled.ExpandMore 24 - import androidx.compose.material3.ElevatedCard 25 23 import androidx.compose.material3.Icon 26 24 import androidx.compose.material3.MaterialTheme 25 + import androidx.compose.material3.OutlinedCard 27 26 import androidx.compose.material3.Text 28 27 import androidx.compose.runtime.Composable 29 28 import androidx.compose.runtime.getValue ··· 38 37 import androidx.compose.ui.text.font.FontWeight 39 38 import androidx.compose.ui.unit.dp 40 39 import com.wasupchucks.data.model.VenueMenu 41 - import com.wasupchucks.ui.theme.StatusClosed 42 40 43 41 @Composable 44 42 fun VenueCard( ··· 47 45 ) { 48 46 var isExpanded by rememberSaveable { mutableStateOf(true) } 49 47 50 - ElevatedCard( 51 - modifier = modifier.fillMaxWidth() 48 + OutlinedCard( 49 + modifier = modifier.fillMaxWidth(), 50 + shape = MaterialTheme.shapes.medium 52 51 ) { 53 52 Column( 54 53 modifier = Modifier 55 54 .fillMaxWidth() 56 - .clip(RoundedCornerShape(12.dp)) 55 + .clip(MaterialTheme.shapes.medium) 57 56 ) { 58 57 // Header 59 58 Row( ··· 66 65 ) { 67 66 Text( 68 67 text = venue.venue, 69 - style = MaterialTheme.typography.titleSmall, 68 + style = MaterialTheme.typography.titleMedium, 70 69 fontWeight = FontWeight.SemiBold, 71 - color = StatusClosed 70 + color = MaterialTheme.colorScheme.primary 72 71 ) 73 72 Icon( 74 73 imageVector = if (isExpanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore, 75 74 contentDescription = if (isExpanded) "Collapse" else "Expand", 76 - tint = StatusClosed 75 + tint = MaterialTheme.colorScheme.primary 77 76 ) 78 77 } 79 78 80 79 // Content 81 80 AnimatedVisibility( 82 81 visible = isExpanded, 83 - enter = fadeIn() + expandVertically(), 84 - exit = fadeOut() + shrinkVertically() 82 + enter = fadeIn( 83 + animationSpec = spring(stiffness = Spring.StiffnessMedium) 84 + ) + expandVertically( 85 + animationSpec = spring( 86 + dampingRatio = Spring.DampingRatioLowBouncy, 87 + stiffness = Spring.StiffnessMedium 88 + ) 89 + ), 90 + exit = fadeOut( 91 + animationSpec = spring(stiffness = Spring.StiffnessMedium) 92 + ) + shrinkVertically( 93 + animationSpec = spring(stiffness = Spring.StiffnessMedium) 94 + ) 85 95 ) { 86 96 Column( 87 97 modifier = Modifier 88 98 .fillMaxWidth() 89 99 .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), 90 - verticalArrangement = Arrangement.spacedBy(8.dp) 100 + verticalArrangement = Arrangement.spacedBy(10.dp) 91 101 ) { 92 102 venue.items.forEach { item -> 93 103 Row( ··· 95 105 .fillMaxWidth() 96 106 .semantics { contentDescription = item.name }, 97 107 verticalAlignment = Alignment.CenterVertically, 98 - horizontalArrangement = Arrangement.spacedBy(8.dp) 108 + horizontalArrangement = Arrangement.spacedBy(12.dp) 99 109 ) { 100 110 // Bullet point 101 111 Box( 102 112 modifier = Modifier 103 - .size(4.dp) 113 + .size(6.dp) 104 114 .background( 105 - MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f), 115 + MaterialTheme.colorScheme.primary.copy(alpha = 0.6f), 106 116 CircleShape 107 117 ) 108 118 ) 109 119 110 120 Text( 111 121 text = item.name, 112 - style = MaterialTheme.typography.bodyMedium, 122 + style = MaterialTheme.typography.bodyLarge, 113 123 modifier = Modifier.weight(1f) 114 124 ) 115 125
+21 -75
android/app/src/main/java/com/wasupchucks/ui/theme/Color.kt
··· 1 1 package com.wasupchucks.ui.theme 2 2 3 + import androidx.compose.material3.ColorScheme 4 + import androidx.compose.runtime.Composable 3 5 import androidx.compose.ui.graphics.Color 4 6 5 - // Primary brand colors 6 - val ChucksGreen = Color(0xFF4CAF50) 7 - val ChucksGreenDark = Color(0xFF388E3C) 8 - val ChucksOrange = Color(0xFFFF9800) 9 - val ChucksOrangeDark = Color(0xFFF57C00) 7 + /** 8 + * Semantic status colors that adapt to the system theme. 9 + * Uses the color scheme's primary for positive states and tertiary for neutral/closed states. 10 + */ 11 + object StatusColors { 12 + val ColorScheme.openStatus: Color 13 + @Composable get() = primary 10 14 11 - // Status colors 12 - val StatusOpen = ChucksGreen 13 - val StatusClosed = ChucksOrange 14 - val StatusOpenContainer = Color(0xFFE8F5E9) 15 - val StatusClosedContainer = Color(0xFFFFF3E0) 15 + val ColorScheme.closedStatus: Color 16 + @Composable get() = tertiary 16 17 17 - // Allergen colors 18 - val AllergenDietary = ChucksGreen 19 - val AllergenWarning = ChucksOrange 20 - val AllergenDietaryContainer = Color(0xFFE8F5E9) 21 - val AllergenWarningContainer = Color(0xFFFFF3E0) 18 + val ColorScheme.openContainer: Color 19 + @Composable get() = primaryContainer 22 20 23 - // Light theme colors 24 - val md_theme_light_primary = Color(0xFF4CAF50) 25 - val md_theme_light_onPrimary = Color(0xFFFFFFFF) 26 - val md_theme_light_primaryContainer = Color(0xFFB8F5B1) 27 - val md_theme_light_onPrimaryContainer = Color(0xFF002204) 28 - val md_theme_light_secondary = Color(0xFF52634F) 29 - val md_theme_light_onSecondary = Color(0xFFFFFFFF) 30 - val md_theme_light_secondaryContainer = Color(0xFFD5E8CF) 31 - val md_theme_light_onSecondaryContainer = Color(0xFF101F10) 32 - val md_theme_light_tertiary = Color(0xFF39656B) 33 - val md_theme_light_onTertiary = Color(0xFFFFFFFF) 34 - val md_theme_light_tertiaryContainer = Color(0xFFBCEBF1) 35 - val md_theme_light_onTertiaryContainer = Color(0xFF001F23) 36 - val md_theme_light_error = Color(0xFFBA1A1A) 37 - val md_theme_light_errorContainer = Color(0xFFFFDAD6) 38 - val md_theme_light_onError = Color(0xFFFFFFFF) 39 - val md_theme_light_onErrorContainer = Color(0xFF410002) 40 - val md_theme_light_background = Color(0xFFFCFDF6) 41 - val md_theme_light_onBackground = Color(0xFF1A1C19) 42 - val md_theme_light_surface = Color(0xFFFCFDF6) 43 - val md_theme_light_onSurface = Color(0xFF1A1C19) 44 - val md_theme_light_surfaceVariant = Color(0xFFDEE5D8) 45 - val md_theme_light_onSurfaceVariant = Color(0xFF424940) 46 - val md_theme_light_outline = Color(0xFF72796F) 47 - val md_theme_light_inverseOnSurface = Color(0xFFF0F1EB) 48 - val md_theme_light_inverseSurface = Color(0xFF2F312D) 49 - val md_theme_light_inversePrimary = Color(0xFF9DD897) 50 - val md_theme_light_surfaceTint = Color(0xFF4CAF50) 51 - val md_theme_light_outlineVariant = Color(0xFFC2C9BD) 52 - val md_theme_light_scrim = Color(0xFF000000) 21 + val ColorScheme.closedContainer: Color 22 + @Composable get() = tertiaryContainer 53 23 54 - // Dark theme colors 55 - val md_theme_dark_primary = Color(0xFF9DD897) 56 - val md_theme_dark_onPrimary = Color(0xFF00390B) 57 - val md_theme_dark_primaryContainer = Color(0xFF005315) 58 - val md_theme_dark_onPrimaryContainer = Color(0xFFB8F5B1) 59 - val md_theme_dark_secondary = Color(0xFFB9CCB3) 60 - val md_theme_dark_onSecondary = Color(0xFF253423) 61 - val md_theme_dark_secondaryContainer = Color(0xFF3B4B39) 62 - val md_theme_dark_onSecondaryContainer = Color(0xFFD5E8CF) 63 - val md_theme_dark_tertiary = Color(0xFFA1CED5) 64 - val md_theme_dark_onTertiary = Color(0xFF00363C) 65 - val md_theme_dark_tertiaryContainer = Color(0xFF1F4D53) 66 - val md_theme_dark_onTertiaryContainer = Color(0xFFBCEBF1) 67 - val md_theme_dark_error = Color(0xFFFFB4AB) 68 - val md_theme_dark_errorContainer = Color(0xFF93000A) 69 - val md_theme_dark_onError = Color(0xFF690005) 70 - val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) 71 - val md_theme_dark_background = Color(0xFF1A1C19) 72 - val md_theme_dark_onBackground = Color(0xFFE2E3DD) 73 - val md_theme_dark_surface = Color(0xFF1A1C19) 74 - val md_theme_dark_onSurface = Color(0xFFE2E3DD) 75 - val md_theme_dark_surfaceVariant = Color(0xFF424940) 76 - val md_theme_dark_onSurfaceVariant = Color(0xFFC2C9BD) 77 - val md_theme_dark_outline = Color(0xFF8C9388) 78 - val md_theme_dark_inverseOnSurface = Color(0xFF1A1C19) 79 - val md_theme_dark_inverseSurface = Color(0xFFE2E3DD) 80 - val md_theme_dark_inversePrimary = Color(0xFF006D21) 81 - val md_theme_dark_surfaceTint = Color(0xFF9DD897) 82 - val md_theme_dark_outlineVariant = Color(0xFF424940) 83 - val md_theme_dark_scrim = Color(0xFF000000) 24 + val ColorScheme.onOpenContainer: Color 25 + @Composable get() = onPrimaryContainer 26 + 27 + val ColorScheme.onClosedContainer: Color 28 + @Composable get() = onTertiaryContainer 29 + }
+19 -69
android/app/src/main/java/com/wasupchucks/ui/theme/Theme.kt
··· 2 2 3 3 import android.os.Build 4 4 import androidx.compose.foundation.isSystemInDarkTheme 5 + import androidx.compose.foundation.shape.RoundedCornerShape 5 6 import androidx.compose.material3.MaterialTheme 7 + import androidx.compose.material3.Shapes 6 8 import androidx.compose.material3.darkColorScheme 7 9 import androidx.compose.material3.dynamicDarkColorScheme 8 10 import androidx.compose.material3.dynamicLightColorScheme 9 11 import androidx.compose.material3.lightColorScheme 10 12 import androidx.compose.runtime.Composable 11 13 import androidx.compose.ui.platform.LocalContext 14 + import androidx.compose.ui.unit.dp 12 15 13 - private val LightColorScheme = lightColorScheme( 14 - primary = md_theme_light_primary, 15 - onPrimary = md_theme_light_onPrimary, 16 - primaryContainer = md_theme_light_primaryContainer, 17 - onPrimaryContainer = md_theme_light_onPrimaryContainer, 18 - secondary = md_theme_light_secondary, 19 - onSecondary = md_theme_light_onSecondary, 20 - secondaryContainer = md_theme_light_secondaryContainer, 21 - onSecondaryContainer = md_theme_light_onSecondaryContainer, 22 - tertiary = md_theme_light_tertiary, 23 - onTertiary = md_theme_light_onTertiary, 24 - tertiaryContainer = md_theme_light_tertiaryContainer, 25 - onTertiaryContainer = md_theme_light_onTertiaryContainer, 26 - error = md_theme_light_error, 27 - errorContainer = md_theme_light_errorContainer, 28 - onError = md_theme_light_onError, 29 - onErrorContainer = md_theme_light_onErrorContainer, 30 - background = md_theme_light_background, 31 - onBackground = md_theme_light_onBackground, 32 - surface = md_theme_light_surface, 33 - onSurface = md_theme_light_onSurface, 34 - surfaceVariant = md_theme_light_surfaceVariant, 35 - onSurfaceVariant = md_theme_light_onSurfaceVariant, 36 - outline = md_theme_light_outline, 37 - inverseOnSurface = md_theme_light_inverseOnSurface, 38 - inverseSurface = md_theme_light_inverseSurface, 39 - inversePrimary = md_theme_light_inversePrimary, 40 - surfaceTint = md_theme_light_surfaceTint, 41 - outlineVariant = md_theme_light_outlineVariant, 42 - scrim = md_theme_light_scrim 16 + // M3 Expressive shapes - larger, more playful radii 17 + val ExpressiveShapes = Shapes( 18 + extraSmall = RoundedCornerShape(8.dp), 19 + small = RoundedCornerShape(12.dp), 20 + medium = RoundedCornerShape(16.dp), 21 + large = RoundedCornerShape(24.dp), 22 + extraLarge = RoundedCornerShape(28.dp) 43 23 ) 44 24 45 - private val DarkColorScheme = darkColorScheme( 46 - primary = md_theme_dark_primary, 47 - onPrimary = md_theme_dark_onPrimary, 48 - primaryContainer = md_theme_dark_primaryContainer, 49 - onPrimaryContainer = md_theme_dark_onPrimaryContainer, 50 - secondary = md_theme_dark_secondary, 51 - onSecondary = md_theme_dark_onSecondary, 52 - secondaryContainer = md_theme_dark_secondaryContainer, 53 - onSecondaryContainer = md_theme_dark_onSecondaryContainer, 54 - tertiary = md_theme_dark_tertiary, 55 - onTertiary = md_theme_dark_onTertiary, 56 - tertiaryContainer = md_theme_dark_tertiaryContainer, 57 - onTertiaryContainer = md_theme_dark_onTertiaryContainer, 58 - error = md_theme_dark_error, 59 - errorContainer = md_theme_dark_errorContainer, 60 - onError = md_theme_dark_onError, 61 - onErrorContainer = md_theme_dark_onErrorContainer, 62 - background = md_theme_dark_background, 63 - onBackground = md_theme_dark_onBackground, 64 - surface = md_theme_dark_surface, 65 - onSurface = md_theme_dark_onSurface, 66 - surfaceVariant = md_theme_dark_surfaceVariant, 67 - onSurfaceVariant = md_theme_dark_onSurfaceVariant, 68 - outline = md_theme_dark_outline, 69 - inverseOnSurface = md_theme_dark_inverseOnSurface, 70 - inverseSurface = md_theme_dark_inverseSurface, 71 - inversePrimary = md_theme_dark_inversePrimary, 72 - surfaceTint = md_theme_dark_surfaceTint, 73 - outlineVariant = md_theme_dark_outlineVariant, 74 - scrim = md_theme_dark_scrim 75 - ) 25 + // Fallback color schemes for devices without dynamic color (pre-Android 12) 26 + private val LightColorScheme = lightColorScheme() 27 + private val DarkColorScheme = darkColorScheme() 76 28 77 29 @Composable 78 30 fun WasupChucksTheme( 79 31 darkTheme: Boolean = isSystemInDarkTheme(), 80 - dynamicColor: Boolean = true, 81 32 content: @Composable () -> Unit 82 33 ) { 83 - val colorScheme = when { 84 - dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { 85 - val context = LocalContext.current 86 - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) 87 - } 88 - darkTheme -> DarkColorScheme 89 - else -> LightColorScheme 34 + val colorScheme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { 35 + val context = LocalContext.current 36 + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) 37 + } else { 38 + if (darkTheme) DarkColorScheme else LightColorScheme 90 39 } 91 40 92 41 MaterialTheme( 93 42 colorScheme = colorScheme, 94 43 typography = Typography, 44 + shapes = ExpressiveShapes, 95 45 content = content 96 46 ) 97 47 }
+1 -1
android/app/src/main/java/com/wasupchucks/widget/ui/LargeWidget.kt
··· 39 39 val statusColor = if (status.isOpen) { 40 40 GlanceTheme.colors.primary 41 41 } else { 42 - GlanceTheme.colors.error 42 + GlanceTheme.colors.tertiary 43 43 } 44 44 45 45 val iconRes = when {
+1 -1
android/app/src/main/java/com/wasupchucks/widget/ui/MediumWidget.kt
··· 38 38 val statusColor = if (status.isOpen) { 39 39 GlanceTheme.colors.primary 40 40 } else { 41 - GlanceTheme.colors.error 41 + GlanceTheme.colors.tertiary 42 42 } 43 43 44 44 val iconRes = when {
+1 -1
android/app/src/main/java/com/wasupchucks/widget/ui/SmallWidget.kt
··· 31 31 val statusColor = if (status.isOpen) { 32 32 GlanceTheme.colors.primary 33 33 } else { 34 - GlanceTheme.colors.error 34 + GlanceTheme.colors.tertiary 35 35 } 36 36 37 37 val iconRes = when {