From dd0d9fba87cedcde9ffaf8e33cc924336fe4d9a6 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Wed, 15 Oct 2025 11:31:06 +0300 Subject: [PATCH] Added Dynamic Colors setting --- .../kotlin/com/tutpro/baresip/AppTheme.kt | 43 ++++++++++------- .../com/tutpro/baresip/BaresipService.kt | 1 + .../main/kotlin/com/tutpro/baresip/Config.kt | 9 ++++ .../com/tutpro/baresip/SettingsScreen.kt | 47 +++++++++++++++++++ app/src/main/res/values/strings.xml | 2 + 5 files changed, 85 insertions(+), 17 deletions(-) diff --git a/app/src/main/kotlin/com/tutpro/baresip/AppTheme.kt b/app/src/main/kotlin/com/tutpro/baresip/AppTheme.kt index 97584345..766f600b 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AppTheme.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AppTheme.kt @@ -1,7 +1,7 @@ package com.tutpro.baresip import android.app.Activity -import android.os.Build +import android.os.Build.VERSION import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme @@ -23,31 +23,40 @@ import androidx.core.view.WindowCompat fun AppTheme( content: @Composable () -> Unit ) { + val context = LocalContext.current val useDarkTheme by remember { BaresipService.darkTheme } + val useDynamicColors by remember { BaresipService.dynamicColors } + + val useActualDynamicColors = useDynamicColors && VERSION.SDK_INT >= 31 + Log.d(TAG, "Use actual dynamic colors: $useActualDynamicColors") val colorScheme = when { - Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { - if (useDarkTheme) - dynamicDarkColorScheme(context = LocalContext.current) + useActualDynamicColors -> { + if (useDarkTheme || isSystemInDarkTheme()) + dynamicDarkColorScheme(context) else - if (isSystemInDarkTheme()) - dynamicDarkColorScheme(context = LocalContext.current) - else - dynamicLightColorScheme(context = LocalContext.current) + dynamicLightColorScheme(context) } - useDarkTheme -> darkColorScheme() - else -> - if (isSystemInDarkTheme()) - darkColorScheme() - else - lightColorScheme() + useDarkTheme || isSystemInDarkTheme() -> darkColorScheme() + else -> lightColorScheme() } - val customColorsPalette = - (if (useDarkTheme) DarkCustomColors else LightCustomColors).copy( + val basePalette = if (useDarkTheme) DarkCustomColors else LightCustomColors + + val customColorsPalette = basePalette.copy( background = colorScheme.background, cardBackground = colorScheme.surfaceVariant, - textFieldBackground = colorScheme.surfaceVariant + textFieldBackground = colorScheme.surfaceVariant, + primary = if (useActualDynamicColors) { + colorScheme.primary + } else { + basePalette.primary + }, + onPrimary = if (useActualDynamicColors) { + colorScheme.onPrimary + } else { + basePalette.onPrimary + } ) val view = LocalView.current diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 30606035..e7bd4df2 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -1750,6 +1750,7 @@ class BaresipService: Service() { val androidContacts = mutableStateOf(emptyList()) val contactNames = mutableStateOf(emptyList()) val darkTheme = mutableStateOf(false) + val dynamicColors = mutableStateOf(false) var messages by mutableStateOf(emptyList()) val messageUpdate = MutableLiveData() val registrationUpdate = MutableLiveData() diff --git a/app/src/main/kotlin/com/tutpro/baresip/Config.kt b/app/src/main/kotlin/com/tutpro/baresip/Config.kt index 84f00746..e7d21977 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Config.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Config.kt @@ -119,6 +119,15 @@ object Config { AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM } + val dynamicColors = previousVariable("dynamic_colors") + BaresipService.dynamicColors.value = if (dynamicColors == "yes") { + config = "${config}dynamic_colors yes\n" + true + } else { + AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM + false + } + val colorblind = previousVariable("colorblind") config = if (colorblind != "") "${config}colorblind $colorblind\n" diff --git a/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt b/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt index a889ac51..6e472171 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt @@ -90,6 +90,8 @@ private var save = false private var oldBatteryOptimizations = false private var oldDarkTheme = false + +private var oldDynamicColors = false private var oldDefaultDialer = false fun NavGraphBuilder.settingsScreenRoute( @@ -104,6 +106,8 @@ fun NavGraphBuilder.settingsScreenRoute( oldDarkTheme = Preferences(ctx).displayTheme == AppCompatDelegate.MODE_NIGHT_YES + oldDynamicColors = BaresipService.dynamicColors.value + if (VERSION.SDK_INT >= 29) { val roleManager = ctx.getSystemService(ROLE_SERVICE) as RoleManager oldDefaultDialer = roleManager.isRoleHeld(RoleManager.ROLE_DIALER) @@ -246,6 +250,8 @@ private var newBatteryOptimizations = false private var newDarkTheme = false +private var newDynamicColors = false + private var newColorblind = false private var newProximitySensing = true @@ -316,6 +322,8 @@ private fun SettingsContent( Ringtone(ctx) BatteryOptimizations() DarkTheme() + if (VERSION.SDK_INT >= 31) + DynamicColors() ColorBlind() ProximitySensing() if (VERSION.SDK_INT >= 29) @@ -1099,6 +1107,38 @@ private fun DarkTheme() { } } +@Composable +private fun DynamicColors() { + Row( + Modifier + .fillMaxWidth() + .padding(end = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Start + ) { + val ctx = LocalContext.current + Text(text = stringResource(R.string.dynamic_colors), + modifier = Modifier + .weight(1f) + .clickable { + alertTitle.value = ctx.getString(R.string.dynamic_colors) + alertMessage.value = ctx.getString(R.string.dynamic_colors_help) + showAlert.value = true + }, + color = LocalCustomColors.current.itemText, + fontSize = 18.sp) + var dynamicColors by remember { mutableStateOf(oldDynamicColors) } + newDynamicColors = dynamicColors + Switch( + checked = dynamicColors, + onCheckedChange = { + dynamicColors = it + newDynamicColors = dynamicColors + } + ) + } +} + @Composable private fun ColorBlind() { Row( @@ -1447,6 +1487,13 @@ private fun checkOnClick(ctx: Context) { save = true } + if (oldDynamicColors != newDynamicColors) { + BaresipService.dynamicColors.value = newDynamicColors + Config.replaceVariable("dynamic_colors", + if (newDynamicColors) "yes" else "no") + save = true + } + if ((Config.variable("colorblind") == "yes") != newColorblind) { Config.replaceVariable( "colorblind", diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3e6cd087..1404d109 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -396,6 +396,8 @@ Country of call ringing, waiting, and callee busy tones Dark Theme Force dark display theme + Dynamic Colors + Use dynamic colors if enabled in Android Settings Colorblind Use colorblind friendly registration status icons Proximity Sensing">