mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-03 16:10:00 +00:00
Merge pull request #7453 from hayaksi1/fix/4639-system-theme
Apply the system theme when switching back to it from a forced light or dark theme
This commit is contained in:
@@ -8,8 +8,11 @@
|
|||||||
|
|
||||||
package io.element.android.compound.theme
|
package io.element.android.compound.theme
|
||||||
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import android.content.res.Configuration
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
@@ -27,12 +30,28 @@ private fun Theme.coerceBlackTheme(allowBlackTheme: Boolean): Theme {
|
|||||||
@Composable
|
@Composable
|
||||||
fun Theme.isDark(): Boolean {
|
fun Theme.isDark(): Boolean {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
Theme.System -> isSystemInDarkTheme()
|
Theme.System -> isSystemThemeDark()
|
||||||
Theme.Dark, Theme.Black -> true
|
Theme.Dark, Theme.Black -> true
|
||||||
Theme.Light -> false
|
Theme.Light -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the system-wide theme is dark.
|
||||||
|
*
|
||||||
|
* This deliberately does not use [androidx.compose.foundation.isSystemInDarkTheme], which reads the activity configuration: `AppCompatDelegate` rewrites
|
||||||
|
* that configuration whenever a non-system theme is selected, so it keeps reporting the previously forced value. The application configuration is left
|
||||||
|
* untouched by AppCompat and is what AppCompat itself reads to expand `MODE_NIGHT_FOLLOW_SYSTEM`.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
private fun isSystemThemeDark(): Boolean {
|
||||||
|
val applicationContext = LocalContext.current.applicationContext
|
||||||
|
val activityConfiguration = LocalConfiguration.current
|
||||||
|
return remember(activityConfiguration) {
|
||||||
|
applicationContext.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Flow<String?>.mapToTheme(allowBlackTheme: Boolean): Flow<Theme> = map {
|
fun Flow<String?>.mapToTheme(allowBlackTheme: Boolean): Flow<Theme> = map {
|
||||||
when (it) {
|
when (it) {
|
||||||
null -> Theme.System
|
null -> Theme.System
|
||||||
|
|||||||
@@ -11,19 +11,22 @@ package io.element.android.compound.theme
|
|||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import app.cash.molecule.RecompositionMode
|
import app.cash.molecule.RecompositionMode
|
||||||
import app.cash.molecule.moleculeFlow
|
import app.cash.molecule.moleculeFlow
|
||||||
import app.cash.turbine.test
|
import app.cash.turbine.test
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.tests.testutils.robolectric.RobolectricTest
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.robolectric.RuntimeEnvironment
|
||||||
|
|
||||||
class ThemeTest {
|
class ThemeTest : RobolectricTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `isDark for System dark returns true`() {
|
fun `isDark for System dark returns true`() {
|
||||||
`isDark for System`(
|
`isDark for System`(
|
||||||
uiMode = Configuration.UI_MODE_NIGHT_YES,
|
systemUiMode = Configuration.UI_MODE_NIGHT_YES,
|
||||||
expected = true,
|
expected = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -31,21 +34,38 @@ class ThemeTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `isDark for System light return false`() {
|
fun `isDark for System light return false`() {
|
||||||
`isDark for System`(
|
`isDark for System`(
|
||||||
uiMode = Configuration.UI_MODE_NIGHT_NO,
|
systemUiMode = Configuration.UI_MODE_NIGHT_NO,
|
||||||
expected = false,
|
expected = false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun `isDark for System`(
|
@Test
|
||||||
uiMode: Int,
|
fun `isDark for System ignores the night mode AppCompat forced on the activity`() {
|
||||||
|
`isDark for System`(
|
||||||
|
systemUiMode = Configuration.UI_MODE_NIGHT_YES,
|
||||||
|
activityUiMode = Configuration.UI_MODE_NIGHT_NO,
|
||||||
|
expected = true,
|
||||||
|
)
|
||||||
|
`isDark for System`(
|
||||||
|
systemUiMode = Configuration.UI_MODE_NIGHT_NO,
|
||||||
|
activityUiMode = Configuration.UI_MODE_NIGHT_YES,
|
||||||
|
expected = false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun `isDark for System`(
|
||||||
|
systemUiMode: Int,
|
||||||
|
activityUiMode: Int = systemUiMode,
|
||||||
expected: Boolean,
|
expected: Boolean,
|
||||||
) = runTest {
|
) = runTest {
|
||||||
|
val application = RuntimeEnvironment.getApplication()
|
||||||
|
application.resources.configuration.uiMode = systemUiMode
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
var result: Boolean? = null
|
var result: Boolean? = null
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
// Let set the system to dark
|
LocalContext provides application,
|
||||||
LocalConfiguration provides Configuration().apply {
|
LocalConfiguration provides Configuration().apply {
|
||||||
this.uiMode = uiMode
|
this.uiMode = activityUiMode
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
result = Theme.System.isDark()
|
result = Theme.System.isDark()
|
||||||
|
|||||||
Reference in New Issue
Block a user