Merge pull request #6441 from timurgilfanov/feature-oled-black
Add Black theme option for battery saving on OLED displays
This commit is contained in:
commit
a82e3425be
44 changed files with 293 additions and 50 deletions
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4be10c3bb9900d27a3b406eca0cb902b0ff9cdf90e8e3cf1ae7760aa7c5d47d9
|
||||
size 377446
|
||||
oid sha256:1f1a277e76d351f48ae0041e082525422604fbf41d77fe078112349855dd3d2e
|
||||
size 453512
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
@ -62,7 +63,7 @@ internal fun IconsCompoundPreviewRtl() = ElementTheme {
|
|||
|
||||
@Preview(widthDp = 730, heightDp = 1920)
|
||||
@Composable
|
||||
internal fun IconsCompoundPreviewDark() = ElementTheme(darkTheme = true) {
|
||||
internal fun IconsCompoundPreviewDark() = ElementTheme(theme = Theme.Dark) {
|
||||
IconsCompoundPreview()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.compound.tokens.generated.compoundColorsHcDark
|
||||
import kotlinx.collections.immutable.ImmutableMap
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
|
|
@ -65,7 +66,7 @@ internal fun CompoundSemanticColorsLightHc() = ElementTheme(
|
|||
|
||||
@Preview(heightDp = 2000)
|
||||
@Composable
|
||||
internal fun CompoundSemanticColorsDark() = ElementTheme(darkTheme = true) {
|
||||
internal fun CompoundSemanticColorsDark() = ElementTheme(theme = Theme.Dark) {
|
||||
Surface {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
|
|
@ -85,7 +86,7 @@ internal fun CompoundSemanticColorsDark() = ElementTheme(darkTheme = true) {
|
|||
@Preview(heightDp = 2000)
|
||||
@Composable
|
||||
internal fun CompoundSemanticColorsDarkHc() = ElementTheme(
|
||||
darkTheme = true,
|
||||
theme = Theme.Dark,
|
||||
compoundDark = compoundColorsHcDark,
|
||||
) {
|
||||
Surface {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ internal fun AvatarColorsPreviewLight() {
|
|||
@Preview
|
||||
@Composable
|
||||
internal fun AvatarColorsPreviewDark() {
|
||||
ElementTheme(darkTheme = true) {
|
||||
ElementTheme(theme = Theme.Dark) {
|
||||
val chunks = avatarColors().chunked(4)
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
for (chunk in chunks) {
|
||||
|
|
|
|||
|
|
@ -77,10 +77,10 @@ internal val LocalCompoundColors = staticCompositionLocalOf { compoundColorsLigh
|
|||
/**
|
||||
* Sets up the theme for the application, or a part of it.
|
||||
*
|
||||
* @param darkTheme whether to use the dark theme or not. If `true`, the dark theme will be used.
|
||||
* @param theme the [Theme] to use. Defaults to [Theme.Dark] or [Theme.Light] based on the system setting.
|
||||
* @param applySystemBarsUpdate whether to update the system bars color scheme or not when the theme changes. It's `true` by default.
|
||||
* This is specially useful when you want to apply an alternate theme to a part of the app but don't want it to affect the system bars.
|
||||
* @param lightStatusBar whether to use a light status bar color scheme or not. By default, it's the opposite of [darkTheme].
|
||||
* @param lightStatusBar whether to use a light status bar color scheme or not. By default, it's `true` for light themes and `false` for dark ones.
|
||||
* @param dynamicColor whether to enable MaterialYou or not. It's `false` by default.
|
||||
* @param compoundLight the [SemanticColors] to use in light theme.
|
||||
* @param compoundDark the [SemanticColors] to use in dark theme.
|
||||
|
|
@ -91,9 +91,9 @@ internal val LocalCompoundColors = staticCompositionLocalOf { compoundColorsLigh
|
|||
*/
|
||||
@Composable
|
||||
fun ElementTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
theme: Theme = if (isSystemInDarkTheme()) Theme.Dark else Theme.Light,
|
||||
applySystemBarsUpdate: Boolean = true,
|
||||
lightStatusBar: Boolean = !darkTheme,
|
||||
lightStatusBar: Boolean = !theme.isDark(),
|
||||
// true to enable MaterialYou
|
||||
dynamicColor: Boolean = false,
|
||||
compoundLight: SemanticColors = compoundColorsLight,
|
||||
|
|
@ -103,8 +103,13 @@ fun ElementTheme(
|
|||
typography: Typography = compoundTypography,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val darkTheme = theme.isDark()
|
||||
val currentCompoundColor = when {
|
||||
darkTheme -> compoundDark
|
||||
darkTheme -> if (theme == Theme.Black) {
|
||||
compoundDark.copy(bgCanvasDefault = Color.Black)
|
||||
} else {
|
||||
compoundDark
|
||||
}
|
||||
else -> compoundLight
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +118,11 @@ fun ElementTheme(
|
|||
val context = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
}
|
||||
darkTheme -> materialColorsDark
|
||||
darkTheme -> if (theme == Theme.Black) {
|
||||
currentCompoundColor.toMaterialColorScheme()
|
||||
} else {
|
||||
materialColorsDark
|
||||
}
|
||||
else -> materialColorsLight
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +139,7 @@ fun ElementTheme(
|
|||
|
||||
if (applySystemBarsUpdate) {
|
||||
val activity = LocalActivity.current as? ComponentActivity
|
||||
LaunchedEffect(statusBarColorScheme, darkTheme, lightStatusBar) {
|
||||
LaunchedEffect(statusBarColorScheme, theme, lightStatusBar) {
|
||||
activity?.enableEdgeToEdge(
|
||||
// For Status bar use the background color of the app
|
||||
statusBarStyle = SystemBarStyle.auto(
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ fun ForcedDarkElementTheme(
|
|||
}
|
||||
}
|
||||
ElementTheme(
|
||||
darkTheme = true,
|
||||
theme = Theme.Dark,
|
||||
compoundLight = colors.light,
|
||||
compoundDark = colors.dark,
|
||||
lightStatusBar = lightStatusBar,
|
||||
|
|
|
|||
|
|
@ -36,11 +36,15 @@ internal fun MaterialTextPreview() = Row(
|
|||
) {
|
||||
MaterialPreview(
|
||||
modifier = Modifier.weight(1f),
|
||||
darkTheme = false,
|
||||
theme = Theme.Light,
|
||||
)
|
||||
MaterialPreview(
|
||||
modifier = Modifier.weight(1f),
|
||||
darkTheme = true,
|
||||
theme = Theme.Dark,
|
||||
)
|
||||
MaterialPreview(
|
||||
modifier = Modifier.weight(1f),
|
||||
theme = Theme.Black,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +56,7 @@ private data class Model(
|
|||
|
||||
@Composable
|
||||
private fun MaterialPreview(
|
||||
darkTheme: Boolean,
|
||||
theme: Theme,
|
||||
modifier: Modifier = Modifier,
|
||||
) = Column(modifier = modifier) {
|
||||
Text(
|
||||
|
|
@ -60,13 +64,13 @@ private fun MaterialPreview(
|
|||
.fillMaxWidth()
|
||||
.padding(8.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
text = if (darkTheme) "Dark" else "Light",
|
||||
text = theme.name,
|
||||
color = Color.Black,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
ElementTheme(
|
||||
darkTheme = darkTheme,
|
||||
theme = theme,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ internal fun ColorsSchemeLightHcPreview() = ElementTheme(
|
|||
@Preview(heightDp = 1200)
|
||||
@Composable
|
||||
internal fun ColorsSchemeDarkPreview() = ElementTheme(
|
||||
darkTheme = true,
|
||||
theme = Theme.Dark,
|
||||
) {
|
||||
ColorsSchemePreview(
|
||||
Color.White,
|
||||
|
|
@ -62,7 +62,7 @@ internal fun ColorsSchemeDarkPreview() = ElementTheme(
|
|||
@Preview(heightDp = 1200)
|
||||
@Composable
|
||||
internal fun ColorsSchemeDarkHcPreview() = ElementTheme(
|
||||
darkTheme = true,
|
||||
theme = Theme.Dark,
|
||||
compoundDark = compoundColorsHcDark,
|
||||
) {
|
||||
ColorsSchemePreview(
|
||||
|
|
@ -71,3 +71,15 @@ internal fun ColorsSchemeDarkHcPreview() = ElementTheme(
|
|||
ElementTheme.materialColors,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(heightDp = 1200)
|
||||
@Composable
|
||||
internal fun ColorsSchemeBlackPreview() = ElementTheme(
|
||||
theme = Theme.Black
|
||||
) {
|
||||
ColorsSchemePreview(
|
||||
Color.White,
|
||||
Color.Black,
|
||||
ElementTheme.materialColors,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,21 +16,26 @@ import kotlinx.coroutines.flow.map
|
|||
enum class Theme {
|
||||
System,
|
||||
Dark,
|
||||
Black,
|
||||
Light,
|
||||
}
|
||||
|
||||
private fun Theme.coerceBlackTheme(allowBlackTheme: Boolean): Theme {
|
||||
return if (this == Theme.Black && !allowBlackTheme) Theme.Dark else this
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Theme.isDark(): Boolean {
|
||||
return when (this) {
|
||||
Theme.System -> isSystemInDarkTheme()
|
||||
Theme.Dark -> true
|
||||
Theme.Dark, Theme.Black -> true
|
||||
Theme.Light -> false
|
||||
}
|
||||
}
|
||||
|
||||
fun Flow<String?>.mapToTheme(): Flow<Theme> = map {
|
||||
fun Flow<String?>.mapToTheme(allowBlackTheme: Boolean): Flow<Theme> = map {
|
||||
when (it) {
|
||||
null -> Theme.System
|
||||
else -> Theme.valueOf(it)
|
||||
}
|
||||
}.coerceBlackTheme(allowBlackTheme)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import io.element.android.compound.previews.IconsCompoundPreviewRtl
|
|||
import io.element.android.compound.previews.IconsPreview
|
||||
import io.element.android.compound.screenshot.utils.screenshotFile
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import org.junit.Test
|
||||
|
|
@ -56,7 +57,7 @@ class CompoundIconTest {
|
|||
val content: List<@Composable ColumnScope.() -> Unit> = CompoundIcons.all.map {
|
||||
@Composable { Icon(imageVector = it, contentDescription = null) }
|
||||
}
|
||||
ElementTheme(darkTheme = true) {
|
||||
ElementTheme(theme = Theme.Dark) {
|
||||
IconsPreview(
|
||||
title = "Compound Vector Icons",
|
||||
content = content.toImmutableList()
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.github.takahirom.roborazzi.captureRoboImage
|
|||
import io.element.android.compound.previews.ColorsSchemePreview
|
||||
import io.element.android.compound.screenshot.utils.screenshotFile
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.theme.Theme
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.annotation.Config
|
||||
|
|
@ -51,7 +52,7 @@ class MaterialYouThemeTest {
|
|||
}
|
||||
}
|
||||
captureRoboImage(file = screenshotFile("MaterialYou Theme - Dark.png")) {
|
||||
ElementTheme(dynamicColor = true, darkTheme = true) {
|
||||
ElementTheme(dynamicColor = true, theme = Theme.Dark) {
|
||||
Surface {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import app.cash.molecule.RecompositionMode
|
|||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
|
|
@ -72,4 +73,14 @@ class ThemeTest {
|
|||
assertThat(awaitItem()).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `mapToTheme falls back to dark when black theme is disabled`() = runTest {
|
||||
flowOf(Theme.Black.name)
|
||||
.mapToTheme(allowBlackTheme = false)
|
||||
.test {
|
||||
assertThat(awaitItem()).isEqualTo(Theme.Dark)
|
||||
awaitComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ dependencies {
|
|||
implementation(projects.libraries.androidutils)
|
||||
implementation(projects.libraries.architecture)
|
||||
implementation(projects.libraries.core)
|
||||
implementation(projects.libraries.featureflag.api)
|
||||
implementation(projects.libraries.preferences.api)
|
||||
implementation(projects.libraries.testtags)
|
||||
implementation(projects.libraries.uiStrings)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import androidx.compose.ui.text.style.TextAlign
|
|||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.annotations.CoreColorToken
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.compound.tokens.generated.internal.DarkColorTokens
|
||||
import io.element.android.compound.tokens.generated.internal.LightColorTokens
|
||||
import io.element.android.libraries.designsystem.R
|
||||
|
|
@ -50,7 +51,7 @@ fun SunsetPage(
|
|||
) {
|
||||
ElementTheme(
|
||||
// Always use the opposite value of the current theme
|
||||
darkTheme = ElementTheme.isLightTheme,
|
||||
theme = if (ElementTheme.isLightTheme) Theme.Dark else Theme.Light,
|
||||
applySystemBarsUpdate = false,
|
||||
) {
|
||||
Box(
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import coil3.asImage
|
|||
import coil3.compose.AsyncImagePreviewHandler
|
||||
import coil3.compose.LocalAsyncImagePreviewHandler
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
|
||||
|
|
@ -26,7 +27,7 @@ import io.element.android.libraries.designsystem.utils.CommonDrawables
|
|||
@Composable
|
||||
@Suppress("ModifierMissing")
|
||||
fun ElementPreview(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
theme: Theme = if (isSystemInDarkTheme()) Theme.Dark else Theme.Light,
|
||||
showBackground: Boolean = true,
|
||||
@DrawableRes
|
||||
drawableFallbackForImages: Int = CommonDrawables.sample_background,
|
||||
|
|
@ -38,7 +39,7 @@ fun ElementPreview(
|
|||
ResourcesCompat.getDrawable(context.resources, drawableFallbackForImages, null)!!.asImage()
|
||||
}
|
||||
) {
|
||||
ElementTheme(darkTheme = darkTheme) {
|
||||
ElementTheme(theme = theme) {
|
||||
if (showBackground) {
|
||||
// If we have a proper contentColor applied we need a Surface instead of a Box
|
||||
Surface(content = content)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.preview
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.element.android.compound.theme.Theme
|
||||
|
||||
@Composable
|
||||
fun ElementPreviewBlack(
|
||||
showBackground: Boolean = true,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
ElementPreview(
|
||||
theme = Theme.Black,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ package io.element.android.libraries.designsystem.preview
|
|||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
|
||||
@Composable
|
||||
|
|
@ -20,7 +21,7 @@ fun ElementPreviewDark(
|
|||
content: @Composable () -> Unit,
|
||||
) {
|
||||
ElementPreview(
|
||||
darkTheme = true,
|
||||
theme = Theme.Dark,
|
||||
showBackground = showBackground,
|
||||
drawableFallbackForImages = drawableFallbackForImages,
|
||||
content = content,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ package io.element.android.libraries.designsystem.preview
|
|||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
|
||||
@Composable
|
||||
|
|
@ -20,7 +21,7 @@ fun ElementPreviewLight(
|
|||
content: @Composable () -> Unit,
|
||||
) {
|
||||
ElementPreview(
|
||||
darkTheme = false,
|
||||
theme = Theme.Light,
|
||||
showBackground = showBackground,
|
||||
drawableFallbackForImages = drawableFallbackForImages,
|
||||
content = content,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
|
||||
@Composable
|
||||
|
|
@ -40,14 +41,14 @@ fun ElementThemedPreview(
|
|||
if (vertical) {
|
||||
Column {
|
||||
ElementPreview(
|
||||
darkTheme = false,
|
||||
theme = Theme.Light,
|
||||
showBackground = showBackground,
|
||||
drawableFallbackForImages = drawableFallbackForImages,
|
||||
content = content,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
ElementPreview(
|
||||
darkTheme = true,
|
||||
theme = Theme.Dark,
|
||||
showBackground = showBackground,
|
||||
drawableFallbackForImages = drawableFallbackForImages,
|
||||
content = content
|
||||
|
|
@ -56,14 +57,14 @@ fun ElementThemedPreview(
|
|||
} else {
|
||||
Row {
|
||||
ElementPreview(
|
||||
darkTheme = false,
|
||||
theme = Theme.Light,
|
||||
showBackground = showBackground,
|
||||
drawableFallbackForImages = drawableFallbackForImages,
|
||||
content = content,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
ElementPreview(
|
||||
darkTheme = true,
|
||||
theme = Theme.Dark,
|
||||
showBackground = showBackground,
|
||||
drawableFallbackForImages = drawableFallbackForImages,
|
||||
content = content
|
||||
|
|
|
|||
|
|
@ -18,11 +18,12 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.compound.theme.isDark
|
||||
import io.element.android.compound.theme.mapToTheme
|
||||
import io.element.android.compound.tokens.generated.SemanticColors
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
|
||||
|
||||
val LocalBuildMeta = staticCompositionLocalOf {
|
||||
|
|
@ -54,21 +55,24 @@ val LocalBuildMeta = staticCompositionLocalOf {
|
|||
@Composable
|
||||
fun ElementThemeApp(
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
featureFlagService: FeatureFlagService,
|
||||
compoundLight: SemanticColors,
|
||||
compoundDark: SemanticColors,
|
||||
buildMeta: BuildMeta,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val theme by remember {
|
||||
appPreferencesStore.getThemeFlow().mapToTheme()
|
||||
}
|
||||
.collectAsState(initial = Theme.System)
|
||||
val isBlackThemeAllowed by remember {
|
||||
featureFlagService.isFeatureEnabledFlow(FeatureFlags.AllowBlackTheme)
|
||||
}.collectAsState(initial = false)
|
||||
val theme by remember(isBlackThemeAllowed) {
|
||||
appPreferencesStore.getThemeFlow().mapToTheme(allowBlackTheme = isBlackThemeAllowed)
|
||||
}.collectAsState(initial = Theme.System)
|
||||
LaunchedEffect(theme) {
|
||||
AppCompatDelegate.setDefaultNightMode(
|
||||
when (theme) {
|
||||
Theme.System -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
Theme.Light -> AppCompatDelegate.MODE_NIGHT_NO
|
||||
Theme.Dark -> AppCompatDelegate.MODE_NIGHT_YES
|
||||
Theme.Dark, Theme.Black -> AppCompatDelegate.MODE_NIGHT_YES
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -76,7 +80,7 @@ fun ElementThemeApp(
|
|||
LocalBuildMeta provides buildMeta,
|
||||
) {
|
||||
ElementTheme(
|
||||
darkTheme = theme.isDark(),
|
||||
theme = theme,
|
||||
content = content,
|
||||
compoundLight = compoundLight,
|
||||
compoundDark = compoundDark,
|
||||
|
|
|
|||
|
|
@ -126,6 +126,13 @@ enum class FeatureFlags(
|
|||
defaultValue = { false },
|
||||
isFinished = false,
|
||||
),
|
||||
AllowBlackTheme(
|
||||
key = "feature.allow_black_theme",
|
||||
title = "Allow black theme",
|
||||
description = "Allow selecting the black appearance theme for battery saving on OLED.",
|
||||
defaultValue = { false },
|
||||
isFinished = false,
|
||||
),
|
||||
LiveLocationSharing(
|
||||
key = "feature.liveLocationSharing",
|
||||
title = "Live location sharing",
|
||||
|
|
|
|||
10
libraries/ui-strings/src/main/res/values/temporary.xml
Normal file
10
libraries/ui-strings/src/main/res/values/temporary.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (c) 2026 Element Creations Ltd.
|
||||
~
|
||||
~ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
~ Please see LICENSE files in the repository root for full details.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<string name="common_black">"Black"</string>
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue