diff --git a/examples/llama.android/app/src/main/java/com/example/llama/MainActivity.kt b/examples/llama.android/app/src/main/java/com/example/llama/MainActivity.kt index 0759b2047b..6ae32ef4f5 100644 --- a/examples/llama.android/app/src/main/java/com/example/llama/MainActivity.kt +++ b/examples/llama.android/app/src/main/java/com/example/llama/MainActivity.kt @@ -67,9 +67,10 @@ class MainActivity : ComponentActivity() { setContent { val settingsViewModel: SettingsViewModel = hiltViewModel() - val themeMode by settingsViewModel.themeMode.collectAsState() + val colorThemeMode by settingsViewModel.colorThemeMode.collectAsState() + val darkThemeMode by settingsViewModel.darkThemeMode.collectAsState() - LlamaTheme(themeMode) { + LlamaTheme(colorThemeMode = colorThemeMode, darkThemeMode = darkThemeMode) { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background diff --git a/examples/llama.android/app/src/main/java/com/example/llama/data/source/prefs/UserPreferences.kt b/examples/llama.android/app/src/main/java/com/example/llama/data/source/prefs/UserPreferences.kt index 3ec68eef05..5f73f3088c 100644 --- a/examples/llama.android/app/src/main/java/com/example/llama/data/source/prefs/UserPreferences.kt +++ b/examples/llama.android/app/src/main/java/com/example/llama/data/source/prefs/UserPreferences.kt @@ -33,15 +33,18 @@ class UserPreferences @Inject constructor ( private val PERFORMANCE_MONITORING_ENABLED = booleanPreferencesKey("performance_monitoring_enabled") private val USE_FAHRENHEIT_TEMPERATURE = booleanPreferencesKey("use_fahrenheit_temperature") private val MONITORING_INTERVAL_MS = longPreferencesKey("monitoring_interval_ms") - private val THEME_MODE = intPreferencesKey("theme_mode") + private val COLOR_THEME_MODE = intPreferencesKey("color_theme_mode") + private val DARK_THEME_MODE = intPreferencesKey("dark_theme_mode") // Constants private const val DEFAULT_MONITORING_INTERVAL_MS = 5000L - // Theme mode values - const val THEME_MODE_AUTO = 0 - const val THEME_MODE_LIGHT = 1 - const val THEME_MODE_DARK = 2 + const val COLOR_THEME_MODE_ARM = 0 + const val COLOR_THEME_MODE_MATERIAL = 1 + + const val DARK_THEME_MODE_AUTO = 0 + const val DARK_THEME_MODE_LIGHT = 1 + const val DARK_THEME_MODE_DARK = 2 } /** @@ -98,19 +101,36 @@ class UserPreferences @Inject constructor ( } /** - * Gets the current theme mode. + * Gets the current color theme mode. */ - fun getThemeMode(): Flow = + fun getColorThemeMode(): Flow = context.settingsDataStore.data.map { preferences -> - preferences[THEME_MODE] ?: THEME_MODE_AUTO + preferences[COLOR_THEME_MODE] ?: COLOR_THEME_MODE_ARM } /** - * Sets the theme mode. + * Sets the color theme mode. */ - suspend fun setThemeMode(mode: Int) = withContext(Dispatchers.IO) { + suspend fun setColorThemeMode(mode: Int) = withContext(Dispatchers.IO) { context.settingsDataStore.edit { preferences -> - preferences[THEME_MODE] = mode + preferences[COLOR_THEME_MODE] = mode + } + } + + /** + * Gets the current dark theme mode. + */ + fun getDarkThemeMode(): Flow = + context.settingsDataStore.data.map { preferences -> + preferences[DARK_THEME_MODE] ?: DARK_THEME_MODE_AUTO + } + + /** + * Sets the dark theme mode. + */ + suspend fun setDarkThemeMode(mode: Int) = withContext(Dispatchers.IO) { + context.settingsDataStore.edit { preferences -> + preferences[DARK_THEME_MODE] = mode } } } diff --git a/examples/llama.android/app/src/main/java/com/example/llama/ui/screens/SettingsGeneralScreen.kt b/examples/llama.android/app/src/main/java/com/example/llama/ui/screens/SettingsGeneralScreen.kt index 64770631ef..c5c9f5f1a4 100644 --- a/examples/llama.android/app/src/main/java/com/example/llama/ui/screens/SettingsGeneralScreen.kt +++ b/examples/llama.android/app/src/main/java/com/example/llama/ui/screens/SettingsGeneralScreen.kt @@ -45,7 +45,8 @@ fun SettingsGeneralScreen( // Collect state from ViewModel val isMonitoringEnabled by viewModel.isMonitoringEnabled.collectAsState() val useFahrenheit by viewModel.useFahrenheitUnit.collectAsState() - val themeMode by viewModel.themeMode.collectAsState() + val colorThemeMode by viewModel.colorThemeMode.collectAsState() + val darkThemeMode by viewModel.darkThemeMode.collectAsState() val detectedTier = viewModel.detectedTier val supportedFeatures = remember(detectedTier) { @@ -80,9 +81,44 @@ fun SettingsGeneralScreen( ) } - SettingsCategory(title = "Theme") { + SettingsCategory(title = "Styling") { + // Color theme mode Text( - text = "Theme Mode", + text = "Color Theme", + style = MaterialTheme.typography.titleMedium + ) + + Text( + text = "ArmĀ® or follow your system dynamic colors", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + + Spacer(modifier = Modifier.height(16.dp)) + + SingleChoiceSegmentedButtonRow( + modifier = Modifier.fillMaxWidth() + ) { + SegmentedButton( + selected = colorThemeMode == UserPreferences.COLOR_THEME_MODE_ARM, + onClick = { viewModel.setColorThemeMode(UserPreferences.COLOR_THEME_MODE_ARM) }, + shape = SegmentedButtonDefaults.itemShape(index = 0, count = 2) + ) { + Text("Arm") + } + + SegmentedButton( + selected = colorThemeMode == UserPreferences.COLOR_THEME_MODE_MATERIAL, + onClick = { viewModel.setColorThemeMode(UserPreferences.COLOR_THEME_MODE_MATERIAL) }, + shape = SegmentedButtonDefaults.itemShape(index = 1, count = 2) + ) { + Text("Material") + } + } + + // Dark theme mode + Text( + text = "Dark Mode", style = MaterialTheme.typography.titleMedium ) @@ -98,24 +134,24 @@ fun SettingsGeneralScreen( modifier = Modifier.fillMaxWidth() ) { SegmentedButton( - selected = themeMode == UserPreferences.THEME_MODE_AUTO, - onClick = { viewModel.setThemeMode(UserPreferences.THEME_MODE_AUTO) }, + selected = darkThemeMode == UserPreferences.DARK_THEME_MODE_AUTO, + onClick = { viewModel.setDarkThemeMode(UserPreferences.DARK_THEME_MODE_AUTO) }, shape = SegmentedButtonDefaults.itemShape(index = 0, count = 3) ) { Text("Auto") } SegmentedButton( - selected = themeMode == UserPreferences.THEME_MODE_LIGHT, - onClick = { viewModel.setThemeMode(UserPreferences.THEME_MODE_LIGHT) }, + selected = darkThemeMode == UserPreferences.DARK_THEME_MODE_LIGHT, + onClick = { viewModel.setDarkThemeMode(UserPreferences.DARK_THEME_MODE_LIGHT) }, shape = SegmentedButtonDefaults.itemShape(index = 1, count = 3) ) { Text("Light") } SegmentedButton( - selected = themeMode == UserPreferences.THEME_MODE_DARK, - onClick = { viewModel.setThemeMode(UserPreferences.THEME_MODE_DARK) }, + selected = darkThemeMode == UserPreferences.DARK_THEME_MODE_DARK, + onClick = { viewModel.setDarkThemeMode(UserPreferences.DARK_THEME_MODE_DARK) }, shape = SegmentedButtonDefaults.itemShape(index = 2, count = 3) ) { Text("Dark") diff --git a/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Color.kt b/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Color.kt index 92e4d594aa..6582b30fc9 100644 --- a/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Color.kt +++ b/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Color.kt @@ -1,66 +1,151 @@ package com.example.llama.ui.theme - +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme import androidx.compose.ui.graphics.Color -// Light Theme Colors -val md_theme_light_primary = Color(0xFF4527A0) -val md_theme_light_onPrimary = Color(0xFFFFFFFF) -val md_theme_light_primaryContainer = Color(0xFFE8DDFF) -val md_theme_light_onPrimaryContainer = Color(0xFF22005D) -val md_theme_light_secondary = Color(0xFF625B71) -val md_theme_light_onSecondary = Color(0xFFFFFFFF) -val md_theme_light_secondaryContainer = Color(0xFFE8DEF8) -val md_theme_light_onSecondaryContainer = Color(0xFF1E192B) -val md_theme_light_tertiary = Color(0xFF7D5260) -val md_theme_light_onTertiary = Color(0xFFFFFFFF) -val md_theme_light_tertiaryContainer = Color(0xFFFFD9E3) -val md_theme_light_onTertiaryContainer = Color(0xFF31101D) -val md_theme_light_error = Color(0xFFBA1A1A) -val md_theme_light_errorContainer = Color(0xFFFFDAD6) -val md_theme_light_onError = Color(0xFFFFFFFF) -val md_theme_light_onErrorContainer = Color(0xFF410002) -val md_theme_light_background = Color(0xFFFFFBFF) -val md_theme_light_onBackground = Color(0xFF1C1B1E) -val md_theme_light_surface = Color(0xFFFFFBFF) -val md_theme_light_onSurface = Color(0xFF1C1B1E) -val md_theme_light_surfaceVariant = Color(0xFFE7E0EB) -val md_theme_light_onSurfaceVariant = Color(0xFF49454E) -val md_theme_light_outline = Color(0xFF7A757F) -val md_theme_light_inverseOnSurface = Color(0xFFF4EFF4) -val md_theme_light_inverseSurface = Color(0xFF313033) -val md_theme_light_inversePrimary = Color(0xFFCFBCFF) -val md_theme_light_surfaceTint = Color(0xFF6750A4) -val md_theme_light_outlineVariant = Color(0xFFCAC4CF) -val md_theme_light_scrim = Color(0xFF000000) -// Dark Theme Colors -val md_theme_dark_primary = Color(0xFFCFBCFF) -val md_theme_dark_onPrimary = Color(0xFF381E72) -val md_theme_dark_primaryContainer = Color(0xFF4F378A) -val md_theme_dark_onPrimaryContainer = Color(0xFFE8DDFF) -val md_theme_dark_secondary = Color(0xFFCBC2DB) -val md_theme_dark_onSecondary = Color(0xFF332D41) -val md_theme_dark_secondaryContainer = Color(0xFF4A4458) -val md_theme_dark_onSecondaryContainer = Color(0xFFE8DEF8) -val md_theme_dark_tertiary = Color(0xFFEFB8C8) -val md_theme_dark_onTertiary = Color(0xFF4A2532) -val md_theme_dark_tertiaryContainer = Color(0xFF633B48) -val md_theme_dark_onTertiaryContainer = Color(0xFFFFD9E3) -val md_theme_dark_error = Color(0xFFFFB4AB) -val md_theme_dark_errorContainer = Color(0xFF93000A) -val md_theme_dark_onError = Color(0xFF690005) -val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) -val md_theme_dark_background = Color(0xFF1C1B1E) -val md_theme_dark_onBackground = Color(0xFFE6E1E6) -val md_theme_dark_surface = Color(0xFF1C1B1E) -val md_theme_dark_onSurface = Color(0xFFE6E1E6) -val md_theme_dark_surfaceVariant = Color(0xFF49454E) -val md_theme_dark_onSurfaceVariant = Color(0xFFCAC4CF) -val md_theme_dark_outline = Color(0xFF948F99) -val md_theme_dark_inverseOnSurface = Color(0xFF1C1B1E) -val md_theme_dark_inverseSurface = Color(0xFFE6E1E6) -val md_theme_dark_inversePrimary = Color(0xFF6750A4) -val md_theme_dark_surfaceTint = Color(0xFFCFBCFF) -val md_theme_dark_outlineVariant = Color(0xFF49454E) +// --- Light Theme Colors --- +val md_theme_light_primary = Color(0xFF0747C9) +val md_theme_light_onPrimary = Color(0xFFCFCFCF) +val md_theme_light_primaryContainer = Color(0xFFD0DEF6) +val md_theme_light_onPrimaryContainer = Color(0xFF1F2227) +val md_theme_light_inversePrimary = Color(0xFFD0DEF6) +// NOT-USED: val md_theme_light_primaryDim = Color(0xFF031E59) +// NOT-USED: val md_theme_light_onPrimaryDim = Color(0xFFCFCFCF) + +val md_theme_light_secondary = Color(0xFFCFCFCF) +val md_theme_light_onSecondary = Color(0xFF1F2227) +val md_theme_light_secondaryContainer = Color(0xFFDFE1E7) +val md_theme_light_onSecondaryContainer = Color(0xFF1F2227) +// NOT-USED: val md_theme_light_secondaryDim = Color(0xFF93B7F8) +// NOT-USED: val md_theme_light_onSecondaryDim = Color(0xFF1F2227) + +val md_theme_light_tertiary = Color(0xFF5613CD) +val md_theme_light_onTertiary = Color(0xFFCFCFCF) +val md_theme_light_tertiaryContainer = Color(0xFFD7D6F7) +val md_theme_light_onTertiaryContainer = Color(0xFF1F2227) +// NOT-USED: val md_theme_light_tertiaryDim = Color(0xFF220857) +// NOT-USED: val md_theme_light_onTertiaryDim = Color(0xFFCFCFCF) + +val md_theme_light_background = Color(0xFFCFCFCF) +val md_theme_light_onBackground = Color(0xFF1F2227) +val md_theme_light_surface = Color(0xFFCFCFCF) +val md_theme_light_onSurface = Color(0xFF1F2227) +val md_theme_light_surfaceVariant = Color(0xFFD0DEF6) +val md_theme_light_onSurfaceVariant = Color(0xFF1F2227) +val md_theme_light_surfaceTint = Color(0xFFDFE1E7) +val md_theme_light_inverseSurface = Color(0xFF737A8B) +val md_theme_light_inverseOnSurface = Color(0xFFCFCFCF) + +val md_theme_light_error = Color(0xFF8F0D11) +val md_theme_light_onError = Color(0xFFCFCFCF) +val md_theme_light_errorContainer = Color(0xFFF5C8C3) +val md_theme_light_onErrorContainer = Color(0xFF1F2227) +// NOT-USED: val md_theme_light_errorDim = Color(0xFF390506) +// NOT-USED: val md_theme_light_onErrorDim = Color(0xFFCFCFCF) + +val md_theme_light_outline = Color(0xFFDFE1E7) +val md_theme_light_outlineVariant = Color(0xFF9BA1B2) +val md_theme_light_scrim = Color(0xFF000000) +// NOT-USED: val md_theme_light_shadow = Color(0x99030304) + + +// TODO: md_theme_light_surfaceBright +val md_theme_light_surfaceContainer = Color(0xFFF0F2F4) +// NOT-USED: val md_theme_light_onSurfaceContainer = Color(0xFF1F2227) +val md_theme_light_surfaceContainerHigh = Color(0xFFDFE1E7) +// NOT-USED: val md_theme_light_onSurfaceContainerHigh = Color(0xFF1F2227) +// TODO: md_theme_light_surfaceContainerHighest +val md_theme_light_surfaceContainerLow = Color(0xFFE9EBEF) +// NOT-USED: val md_theme_light_onSurfaceContainerLow = Color(0xFF1F2227) +// TODO: md_theme_light_surfaceContainerLowest +// TODO: md_theme_light_surfaceDim + +val md_theme_light_primaryFixed = Color(0xFF0747C9) +val md_theme_light_primaryFixedDim = Color(0xFF04359B) +val md_theme_light_onPrimaryFixed = Color(0xFFCFCFCF) +val md_theme_light_onPrimaryFixedVariant = Color(0xFF2F333B) + +val md_theme_light_secondaryFixed = Color(0xFFCFCFCF) +val md_theme_light_secondaryFixedDim = Color(0xFFE9EBEF) +val md_theme_light_onSecondaryFixed = Color(0xFF1F2227) +val md_theme_light_onSecondaryFixedVariant = Color(0xFF2F333B) + +val md_theme_light_tertiaryFixed = Color(0xFF5613CD) +val md_theme_light_tertiaryFixedDim = Color(0xFF220857) +val md_theme_light_onTertiaryFixed = Color(0xFFCFCFCF) +val md_theme_light_onTertiaryFixedVariant = Color(0xFFDFE1E7) + + +// --- Dark Theme Colors --- +val md_theme_dark_primary = Color(0xFF0747C9) +val md_theme_dark_onPrimary = Color(0xFFCFCFCF) +val md_theme_dark_primaryContainer = Color(0xFF020D2B) +val md_theme_dark_onPrimaryContainer = Color(0xFFCFCFCF) +val md_theme_dark_inversePrimary = Color(0xFF020D2B) +// NOT-USED: val md_theme_dark_primaryDim = Color(0xFF031E59) +// NOT-USED: val md_theme_dark_onPrimaryDim = Color(0xFFCFCFCF) + +val md_theme_dark_secondary = Color(0xFF1F2227) +val md_theme_dark_onSecondary = Color(0xFFCFCFCF) +val md_theme_dark_secondaryContainer = Color(0xFF2F333B) +val md_theme_dark_onSecondaryContainer = Color(0xFFCFCFCF) +// NOT-USED: val md_theme_dark_secondaryDim = Color(0xFF031E59) +// NOT-USED: val md_theme_dark_onSecondaryDim = Color(0xFFCFCFCF) + +val md_theme_dark_tertiary = Color(0xFF5613CD) +val md_theme_dark_onTertiary = Color(0xFFCFCFCF) +val md_theme_dark_tertiaryContainer = Color(0xFF0F0429) +val md_theme_dark_onTertiaryContainer = Color(0xFFCFCFCF) +// NOT-USED: val md_theme_dark_tertiaryDim = Color(0xFF220857) +// NOT-USED: val md_theme_dark_onTertiaryDim = Color(0xFFCFCFCF) + +val md_theme_dark_background = Color(0xFF0F1216) +val md_theme_dark_onBackground = Color(0xFFCFCFCF) +val md_theme_dark_surface = Color(0xFF0F1216) +val md_theme_dark_onSurface = Color(0xFFCFCFCF) +val md_theme_dark_surfaceVariant = Color(0xFF020D2B) +val md_theme_dark_onSurfaceVariant = Color(0xFFCFCFCF) +val md_theme_dark_surfaceTint = Color(0xFF2F333B) +val md_theme_dark_inverseSurface = Color(0xFF8A92A5) +val md_theme_dark_inverseOnSurface = Color(0xFFCFCFCF) + +val md_theme_dark_error = Color(0xFF8F0D11) +val md_theme_dark_onError = Color(0xFFCFCFCF) +val md_theme_dark_errorContainer = Color(0xFF180203) +val md_theme_dark_onErrorContainer = Color(0xFFCFCFCF) +// NOT-USED: val md_theme_dark_errorDim = Color(0xFF390506) +// NOT-USED: val md_theme_dark_onErrorDim = Color(0xFFCFCFCF) + +val md_theme_dark_outline = Color(0xFF40454F) +val md_theme_dark_outlineVariant = Color(0xFF8A92A5) val md_theme_dark_scrim = Color(0xFF000000) +// NOT-USED: val md_theme_dark_shadow = Color(0xFF2F333B) + +// TODO: md_theme_dark_surfaceBright +val md_theme_dark_surfaceContainer = Color(0xFF030304) +// NOT-USED: val md_theme_dark_onSurfaceContainer = Color(0xFFFCFCFC) +val md_theme_dark_surfaceContainerLow = Color(0xFF1F2227) +// NOT-USED: val md_theme_dark_onSurfaceContainerLow = Color(0xFFFCFCFC) +// TODO: md_theme_dark_surfaceContainerHighest +val md_theme_dark_surfaceContainerHigh = Color(0xFF2F333B) +// NOT-USED: val md_theme_dark_onSurfaceContainerHigh = Color(0xFFCFCFCF) +// TODO: md_theme_dark_surfaceContainerLowest +// TODO: md_theme_dark_surfaceDim + +val md_theme_dark_primaryFixed = Color(0xFF0747C9) +val md_theme_dark_primaryFixedDim = Color(0xFF04359B) +val md_theme_dark_onPrimaryFixed = Color(0xFFCFCFCF) +val md_theme_dark_onPrimaryFixedVariant = Color(0xFFDFE1E7) + +val md_theme_dark_secondaryFixed = Color(0xFF1F2227) +val md_theme_dark_secondaryFixedDim = Color(0xFF40454F) +val md_theme_dark_onSecondaryFixed = Color(0xFFCFCFCF) +val md_theme_dark_onSecondaryFixedVariant = Color(0xFFDFE1E7) + +val md_theme_dark_tertiaryFixed = Color(0xFF5613CD) +val md_theme_dark_tertiaryFixedDim = Color(0xFF220857) +val md_theme_dark_onTertiaryFixed = Color(0xFFCFCFCF) +val md_theme_dark_onTertiaryFixedVariant = Color(0xFFDFE1E7) diff --git a/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Theme.kt b/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Theme.kt index 6240e79c02..e0e0f923da 100644 --- a/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Theme.kt +++ b/examples/llama.android/app/src/main/java/com/example/llama/ui/theme/Theme.kt @@ -2,6 +2,7 @@ package com.example.llama.ui.theme import android.app.Activity import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme import androidx.compose.material3.dynamicDarkColorScheme @@ -14,87 +15,152 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat import com.example.llama.data.source.prefs.UserPreferences +import com.example.llama.data.source.prefs.UserPreferences.Companion.COLOR_THEME_MODE_ARM +import com.example.llama.data.source.prefs.UserPreferences.Companion.COLOR_THEME_MODE_MATERIAL import com.google.accompanist.systemuicontroller.rememberSystemUiController -// TODO-han.yin: support more / custom color palettes? -private val LightColorScheme = lightColorScheme( +// -------------------- ColorScheme -------------------- +internal val armLightColorScheme: ColorScheme = lightColorScheme( primary = md_theme_light_primary, onPrimary = md_theme_light_onPrimary, primaryContainer = md_theme_light_primaryContainer, onPrimaryContainer = md_theme_light_onPrimaryContainer, + inversePrimary = md_theme_light_inversePrimary, + secondary = md_theme_light_secondary, onSecondary = md_theme_light_onSecondary, secondaryContainer = md_theme_light_secondaryContainer, onSecondaryContainer = md_theme_light_onSecondaryContainer, + tertiary = md_theme_light_tertiary, onTertiary = md_theme_light_onTertiary, tertiaryContainer = md_theme_light_tertiaryContainer, onTertiaryContainer = md_theme_light_onTertiaryContainer, - error = md_theme_light_error, - errorContainer = md_theme_light_errorContainer, - onError = md_theme_light_onError, - onErrorContainer = md_theme_light_onErrorContainer, + background = md_theme_light_background, onBackground = md_theme_light_onBackground, surface = md_theme_light_surface, onSurface = md_theme_light_onSurface, surfaceVariant = md_theme_light_surfaceVariant, onSurfaceVariant = md_theme_light_onSurfaceVariant, - outline = md_theme_light_outline, - inverseOnSurface = md_theme_light_inverseOnSurface, - inverseSurface = md_theme_light_inverseSurface, - inversePrimary = md_theme_light_inversePrimary, surfaceTint = md_theme_light_surfaceTint, + inverseSurface = md_theme_light_inverseSurface, + inverseOnSurface = md_theme_light_inverseOnSurface, + + error = md_theme_light_error, + onError = md_theme_light_onError, + errorContainer = md_theme_light_errorContainer, + onErrorContainer = md_theme_light_onErrorContainer, + + outline = md_theme_light_outline, outlineVariant = md_theme_light_outlineVariant, scrim = md_theme_light_scrim, + + // TODO: surfaceBright = md_theme_light_surfaceBright, + surfaceContainer = md_theme_light_surfaceContainer, + surfaceContainerHigh = md_theme_light_surfaceContainerHigh, + // TODO: surfaceContainerHighest = md_theme_light_surfaceContainerHighest, + surfaceContainerLow = md_theme_light_surfaceContainerLow, + // TODO: surfaceContainerLowest = md_theme_light_surfaceContainerLowest, + // TODO: surfaceDim = md_theme_light_surfaceDim, + + primaryFixed = md_theme_light_primaryFixed, + primaryFixedDim = md_theme_light_primaryFixedDim, + onPrimaryFixed = md_theme_light_onPrimaryFixed, + onPrimaryFixedVariant = md_theme_light_onPrimaryFixedVariant, + + secondaryFixed = md_theme_light_secondaryFixed, + secondaryFixedDim = md_theme_light_secondaryFixedDim, + onSecondaryFixed = md_theme_light_onSecondaryFixed, + onSecondaryFixedVariant = md_theme_light_onSecondaryFixedVariant, + + tertiaryFixed = md_theme_light_tertiaryFixed, + tertiaryFixedDim = md_theme_light_tertiaryFixedDim, + onTertiaryFixed = md_theme_light_onTertiaryFixed, + onTertiaryFixedVariant = md_theme_light_onTertiaryFixedVariant, ) -private val DarkColorScheme = darkColorScheme( + +internal val armDarkColorScheme: ColorScheme = darkColorScheme( primary = md_theme_dark_primary, onPrimary = md_theme_dark_onPrimary, primaryContainer = md_theme_dark_primaryContainer, onPrimaryContainer = md_theme_dark_onPrimaryContainer, + inversePrimary = md_theme_dark_inversePrimary, + secondary = md_theme_dark_secondary, onSecondary = md_theme_dark_onSecondary, secondaryContainer = md_theme_dark_secondaryContainer, onSecondaryContainer = md_theme_dark_onSecondaryContainer, + tertiary = md_theme_dark_tertiary, onTertiary = md_theme_dark_onTertiary, tertiaryContainer = md_theme_dark_tertiaryContainer, onTertiaryContainer = md_theme_dark_onTertiaryContainer, - error = md_theme_dark_error, - errorContainer = md_theme_dark_errorContainer, - onError = md_theme_dark_onError, - onErrorContainer = md_theme_dark_onErrorContainer, + background = md_theme_dark_background, onBackground = md_theme_dark_onBackground, surface = md_theme_dark_surface, onSurface = md_theme_dark_onSurface, surfaceVariant = md_theme_dark_surfaceVariant, onSurfaceVariant = md_theme_dark_onSurfaceVariant, - outline = md_theme_dark_outline, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inverseSurface = md_theme_dark_inverseSurface, - inversePrimary = md_theme_dark_inversePrimary, surfaceTint = md_theme_dark_surfaceTint, + inverseSurface = md_theme_dark_inverseSurface, + inverseOnSurface = md_theme_dark_inverseOnSurface, + + error = md_theme_dark_error, + onError = md_theme_dark_onError, + errorContainer = md_theme_dark_errorContainer, + onErrorContainer = md_theme_dark_onErrorContainer, + + outline = md_theme_dark_outline, outlineVariant = md_theme_dark_outlineVariant, scrim = md_theme_dark_scrim, + + // TODO: surfaceBright = md_theme_dark_surfaceBright, + surfaceContainer = md_theme_dark_surfaceContainer, + surfaceContainerHigh = md_theme_dark_surfaceContainerHigh, + // TODO: surfaceContainerHighest = md_theme_dark_surfaceContainerHighest, + surfaceContainerLow = md_theme_dark_surfaceContainerLow, + // TODO: surfaceContainerLowest = md_theme_dark_surfaceContainerLowest, + // TODO: surfaceDim = md_theme_dark_surfaceDim, + + primaryFixed = md_theme_dark_primaryFixed, + primaryFixedDim = md_theme_dark_primaryFixedDim, + onPrimaryFixed = md_theme_dark_onPrimaryFixed, + onPrimaryFixedVariant = md_theme_dark_onPrimaryFixedVariant, + + secondaryFixed = md_theme_dark_secondaryFixed, + secondaryFixedDim = md_theme_dark_secondaryFixedDim, + onSecondaryFixed = md_theme_dark_onSecondaryFixed, + onSecondaryFixedVariant = md_theme_dark_onSecondaryFixedVariant, + + tertiaryFixed = md_theme_dark_tertiaryFixed, + tertiaryFixedDim = md_theme_dark_tertiaryFixedDim, + onTertiaryFixed = md_theme_dark_onTertiaryFixed, + onTertiaryFixedVariant = md_theme_dark_onTertiaryFixedVariant, ) @Composable fun LlamaTheme( - themeMode: Int = UserPreferences.THEME_MODE_AUTO, + colorThemeMode: Int, + darkThemeMode: Int, content: @Composable () -> Unit ) { - val darkTheme = when (themeMode) { - UserPreferences.THEME_MODE_LIGHT -> false - UserPreferences.THEME_MODE_DARK -> true + val darkTheme = when (darkThemeMode) { + UserPreferences.DARK_THEME_MODE_LIGHT -> false + UserPreferences.DARK_THEME_MODE_DARK -> true else -> isSystemInDarkTheme() } val context = LocalContext.current - val colorScheme = - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + + val colorScheme = when(colorThemeMode) { + COLOR_THEME_MODE_ARM -> if (darkTheme) armDarkColorScheme else armLightColorScheme + COLOR_THEME_MODE_MATERIAL -> + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + else -> error("Unexpected color theme $colorThemeMode") + } val view = LocalView.current if (!view.isInEditMode) { diff --git a/examples/llama.android/app/src/main/java/com/example/llama/viewmodel/SettingsViewModel.kt b/examples/llama.android/app/src/main/java/com/example/llama/viewmodel/SettingsViewModel.kt index 6a102fa88a..91fdf29a80 100644 --- a/examples/llama.android/app/src/main/java/com/example/llama/viewmodel/SettingsViewModel.kt +++ b/examples/llama.android/app/src/main/java/com/example/llama/viewmodel/SettingsViewModel.kt @@ -44,11 +44,10 @@ class SettingsViewModel @Inject constructor( private val _batteryInfo = MutableStateFlow(BatteryMetrics(0, false)) val batteryInfo: StateFlow = _batteryInfo.asStateFlow() - // Temperature information + // User preferences: monitoring private val _temperatureMetrics = MutableStateFlow(TemperatureMetrics(0f, TemperatureWarningLevel.NORMAL)) val temperatureMetrics: StateFlow = _temperatureMetrics.asStateFlow() - // User preferences private val _isMonitoringEnabled = MutableStateFlow(true) val isMonitoringEnabled: StateFlow = _isMonitoringEnabled.asStateFlow() @@ -58,8 +57,12 @@ class SettingsViewModel @Inject constructor( private val _monitoringInterval = MutableStateFlow(5000L) val monitoringInterval: StateFlow = _monitoringInterval.asStateFlow() - private val _themeMode = MutableStateFlow(UserPreferences.THEME_MODE_AUTO) - val themeMode: StateFlow = _themeMode.asStateFlow() + // User preferences: themes + private val _colorThemeMode = MutableStateFlow(UserPreferences.COLOR_THEME_MODE_ARM) + val colorThemeMode: StateFlow = _colorThemeMode.asStateFlow() + + private val _darkThemeMode = MutableStateFlow(UserPreferences.DARK_THEME_MODE_AUTO) + val darkThemeMode: StateFlow = _darkThemeMode.asStateFlow() val detectedTier: LLamaTier? get() = tierDetection.detectedTier @@ -70,18 +73,26 @@ class SettingsViewModel @Inject constructor( _isMonitoringEnabled.value = userPreferences.isPerformanceMonitoringEnabled().first() _useFahrenheitUnit.value = userPreferences.usesFahrenheitTemperature().first() _monitoringInterval.value = userPreferences.getMonitoringInterval().first() - _themeMode.value = userPreferences.getThemeMode().first() + _colorThemeMode.value = userPreferences.getColorThemeMode().first() + _darkThemeMode.value = userPreferences.getDarkThemeMode().first() // Start monitoring if enabled if (_isMonitoringEnabled.value) { startMonitoring() } - viewModelScope.launch { - userPreferences.getThemeMode().collect { mode -> - _themeMode.value = mode - } - } +// viewModelScope.launch { +// launch { +// userPreferences.getColorThemeMode().collect { mode -> +// _colorThemeMode.value = mode +// } +// } +// launch { +// userPreferences.getDarkThemeMode().collect { mode -> +// _darkThemeMode.value = mode +// } +// } +// } } } @@ -158,12 +169,22 @@ class SettingsViewModel @Inject constructor( } /** - * Sets the theme mode. + * Sets the color theme mode. */ - fun setThemeMode(mode: Int) { + fun setColorThemeMode(mode: Int) { viewModelScope.launch { - userPreferences.setThemeMode(mode) - _themeMode.value = mode + userPreferences.setColorThemeMode(mode) + _colorThemeMode.value = mode + } + } + + /** + * Sets the dark theme mode. + */ + fun setDarkThemeMode(mode: Int) { + viewModelScope.launch { + userPreferences.setDarkThemeMode(mode) + _darkThemeMode.value = mode } } }