From 8ba719a3c8c9cc33f804495fef9642d0c60effb6 Mon Sep 17 00:00:00 2001 From: Rui Date: Fri, 15 Mar 2024 18:12:27 -0400 Subject: [PATCH 1/2] Observe system theme --- .../dydx/platformui/designSystem/theme/ThemeConfig.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/v4/platformUI/src/main/java/exchange/dydx/platformui/designSystem/theme/ThemeConfig.kt b/v4/platformUI/src/main/java/exchange/dydx/platformui/designSystem/theme/ThemeConfig.kt index 1ea60bb0..6365b8f9 100644 --- a/v4/platformUI/src/main/java/exchange/dydx/platformui/designSystem/theme/ThemeConfig.kt +++ b/v4/platformUI/src/main/java/exchange/dydx/platformui/designSystem/theme/ThemeConfig.kt @@ -1,6 +1,8 @@ package exchange.dydx.platformui.designSystem.theme import android.content.Context +import android.content.res.Configuration +import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.util.Log import exchange.dydx.utilities.utils.JsonUtils import exchange.dydx.utilities.utils.SharedPreferencesStore @@ -47,6 +49,7 @@ data class ThemeConfig( "dark" -> dark(context) "light" -> light(context) "classic_dark" -> classicDark(context) + "system" -> if (context.isDarkThemeOn()) dark(context) else light(context) else -> null } @@ -57,6 +60,11 @@ data class ThemeConfig( config } } + + private fun Context.isDarkThemeOn(): Boolean { + return resources.configuration.uiMode and + Configuration.UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES + } } } From 50f847c72920e840cf68fb2b8e60a37f5d398568 Mon Sep 17 00:00:00 2001 From: Rui Date: Fri, 15 Mar 2024 18:47:11 -0400 Subject: [PATCH 2/2] Recompose when theme changes --- .../exchange/dydx/trading/TradingActivity.kt | 58 +++++++++++++------ 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/v4/core/src/main/java/exchange/dydx/trading/TradingActivity.kt b/v4/core/src/main/java/exchange/dydx/trading/TradingActivity.kt index cd45dbaa..fc459a96 100644 --- a/v4/core/src/main/java/exchange/dydx/trading/TradingActivity.kt +++ b/v4/core/src/main/java/exchange/dydx/trading/TradingActivity.kt @@ -6,6 +6,10 @@ import android.os.Bundle import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.key +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.setValue import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.Modifier import androidx.core.view.WindowCompat @@ -26,8 +30,11 @@ import exchange.dydx.trading.core.CoreViewModel import exchange.dydx.trading.core.DydxNavGraph import exchange.dydx.trading.core.biometric.DydxBiometricPrompt import exchange.dydx.trading.core.biometric.DydxBiometricView +import exchange.dydx.trading.feature.shared.PreferenceKeys +import exchange.dydx.utilities.utils.SharedPreferencesStore import kotlinx.coroutines.launch import timber.log.Timber +import javax.inject.Inject private const val TAG = "TradingActivity" @@ -44,6 +51,9 @@ class TradingActivity : FragmentActivity() { // This is the main ViewModel that the Activity will use to communicate with Compose-scoped code. private val viewModel: CoreViewModel by viewModels() + @Inject + lateinit var preferencesStore: SharedPreferencesStore + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -121,14 +131,16 @@ class TradingActivity : FragmentActivity() { @Composable private fun MainContent() { - PlatformInfoScaffold( - modifier = Modifier, - platformInfo = viewModel.platformInfo, - ) { - DydxNavGraph( - appRouter = viewModel.router, + key(themeChangedState) { + PlatformInfoScaffold( modifier = Modifier, - ) + platformInfo = viewModel.platformInfo, + ) { + DydxNavGraph( + appRouter = viewModel.router, + modifier = Modifier, + ) + } } } @@ -152,20 +164,32 @@ class TradingActivity : FragmentActivity() { } } + // This is a state that is used to force a recomposition when the theme changes. + private var themeChangedState by mutableIntStateOf(0) + override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) - when (newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK) { - Configuration.UI_MODE_NIGHT_NO -> { - // Night mode is not active, we're using the light theme - ThemeSettings.shared.themeConfig.value = ThemeConfig.light(this) - ThemeSettings.shared.colorMap = mapOf() - } + val theme = preferencesStore.read(key = PreferenceKeys.Theme) + if (theme == "system") { + when (newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK) { + Configuration.UI_MODE_NIGHT_NO -> { + // Night mode is not active, we're using the light theme + if (ThemeSettings.shared.themeConfig.value != ThemeConfig.light(this)) { + ThemeSettings.shared.themeConfig.value = ThemeConfig.light(this) + ThemeSettings.shared.colorMap = mapOf() + themeChangedState++ + } + } - Configuration.UI_MODE_NIGHT_YES -> { - // Night mode is active, we're using dark theme - ThemeSettings.shared.themeConfig.value = ThemeConfig.dark(this) - ThemeSettings.shared.colorMap = mapOf() + Configuration.UI_MODE_NIGHT_YES -> { + // Night mode is active, we're using dark theme + if (ThemeSettings.shared.themeConfig.value != ThemeConfig.dark(this)) { + ThemeSettings.shared.themeConfig.value = ThemeConfig.dark(this) + ThemeSettings.shared.colorMap = mapOf() + themeChangedState++ + } + } } } }