🚀 Absolute Dark setting
* Added new "Absolute Dark" setting, which darkens "Pure Dark" theme even more, giving it completely black color as background * May be more suitable for OLED screen users, while default "Pure Dark" may be better for non-OLED display users
This commit is contained in:
parent
be9b28834c
commit
63bb317865
9 changed files with 100 additions and 46 deletions
|
|
@ -11,6 +11,7 @@ object DataStoreConstants {
|
||||||
val THEME = stringPreferencesKey("theme")
|
val THEME = stringPreferencesKey("theme")
|
||||||
val DARK_THEME = stringPreferencesKey("dark_theme")
|
val DARK_THEME = stringPreferencesKey("dark_theme")
|
||||||
val PURE_DARK = stringPreferencesKey("pure_dark")
|
val PURE_DARK = stringPreferencesKey("pure_dark")
|
||||||
|
val ABSOLUTE_DARK = booleanPreferencesKey("absolute_dark")
|
||||||
val THEME_CONTRAST = stringPreferencesKey("theme_contrast")
|
val THEME_CONTRAST = stringPreferencesKey("theme_contrast")
|
||||||
val SHOW_START_SCREEN = booleanPreferencesKey("guide")
|
val SHOW_START_SCREEN = booleanPreferencesKey("guide")
|
||||||
val CHECK_FOR_UPDATES = booleanPreferencesKey("check_for_updates")
|
val CHECK_FOR_UPDATES = booleanPreferencesKey("check_for_updates")
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,5 @@ sealed class MainEvent {
|
||||||
data class OnChangeTextAlignment(val alignment: String) : MainEvent()
|
data class OnChangeTextAlignment(val alignment: String) : MainEvent()
|
||||||
data class OnChangeDoublePressExit(val bool: Boolean) : MainEvent()
|
data class OnChangeDoublePressExit(val bool: Boolean) : MainEvent()
|
||||||
data class OnChangeLetterSpacing(val spacing: Int) : MainEvent()
|
data class OnChangeLetterSpacing(val spacing: Int) : MainEvent()
|
||||||
|
data class OnChangeAbsoluteDark(val bool: Boolean) : MainEvent()
|
||||||
}
|
}
|
||||||
|
|
@ -51,6 +51,7 @@ data class MainState(
|
||||||
},
|
},
|
||||||
val darkTheme: DarkTheme = provideDefaultValue { DarkTheme.FOLLOW_SYSTEM },
|
val darkTheme: DarkTheme = provideDefaultValue { DarkTheme.FOLLOW_SYSTEM },
|
||||||
val pureDark: PureDark = provideDefaultValue { PureDark.OFF },
|
val pureDark: PureDark = provideDefaultValue { PureDark.OFF },
|
||||||
|
val absoluteDark: Boolean = provideDefaultValue { false },
|
||||||
val themeContrast: ThemeContrast = provideDefaultValue { ThemeContrast.STANDARD },
|
val themeContrast: ThemeContrast = provideDefaultValue { ThemeContrast.STANDARD },
|
||||||
val showStartScreen: Boolean = provideDefaultValue { true },
|
val showStartScreen: Boolean = provideDefaultValue { true },
|
||||||
val checkForUpdates: Boolean = provideDefaultValue { false },
|
val checkForUpdates: Boolean = provideDefaultValue { false },
|
||||||
|
|
@ -118,6 +119,10 @@ data class MainState(
|
||||||
PURE_DARK, convert = { toPureDark() }
|
PURE_DARK, convert = { toPureDark() }
|
||||||
) { pureDark },
|
) { pureDark },
|
||||||
|
|
||||||
|
absoluteDark = provideValue(
|
||||||
|
ABSOLUTE_DARK
|
||||||
|
) { absoluteDark },
|
||||||
|
|
||||||
themeContrast = provideValue(
|
themeContrast = provideValue(
|
||||||
THEME_CONTRAST, convert = { toThemeContrast() }
|
THEME_CONTRAST, convert = { toThemeContrast() }
|
||||||
) { themeContrast },
|
) { themeContrast },
|
||||||
|
|
|
||||||
|
|
@ -373,6 +373,20 @@ class MainViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is MainEvent.OnChangeAbsoluteDark -> {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
setDatastore.execute(
|
||||||
|
DataStoreConstants.ABSOLUTE_DARK,
|
||||||
|
event.bool
|
||||||
|
)
|
||||||
|
updateStateWithSavedHandle {
|
||||||
|
it.copy(
|
||||||
|
absoluteDark = event.bool
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
||||||
|
import ua.acclorite.book_story.presentation.ui.isPureDark
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute Dark setting.
|
||||||
|
* If true, changes Pure Dark (OLED) theme to have black color as background.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun AbsoluteDarkSetting() {
|
||||||
|
val state = LocalMainViewModel.current.state
|
||||||
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
ExpandingTransition(visible = state.value.pureDark.isPureDark(context)) {
|
||||||
|
SwitchWithTitle(
|
||||||
|
selected = state.value.absoluteDark,
|
||||||
|
title = stringResource(id = R.string.absolute_dark_option),
|
||||||
|
description = stringResource(id = R.string.absolute_dark_option_desc),
|
||||||
|
onClick = {
|
||||||
|
onMainEvent(
|
||||||
|
MainEvent.OnChangeAbsoluteDark(
|
||||||
|
!state.value.absoluteDark
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ import androidx.compose.ui.unit.coerceAtLeast
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.presentation.core.components.CategoryTitle
|
import ua.acclorite.book_story.presentation.core.components.CategoryTitle
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.AbsoluteDarkSetting
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.DarkThemeSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.DarkThemeSetting
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.PureDarkSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.PureDarkSetting
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.ThemeContrastSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.ThemeContrastSetting
|
||||||
|
|
@ -66,6 +67,10 @@ fun LazyListScope.ThemePreferencesSubcategory(
|
||||||
PureDarkSetting()
|
PureDarkSetting()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
AbsoluteDarkSetting()
|
||||||
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
Spacer(
|
Spacer(
|
||||||
modifier = Modifier.height(bottomPadding)
|
modifier = Modifier.height(bottomPadding)
|
||||||
|
|
|
||||||
|
|
@ -3,61 +3,48 @@ package ua.acclorite.book_story.presentation.ui.theme
|
||||||
import androidx.compose.material3.ColorScheme
|
import androidx.compose.material3.ColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun blackTheme(initialTheme: ColorScheme): ColorScheme {
|
fun blackTheme(initialTheme: ColorScheme): ColorScheme {
|
||||||
|
val absoluteDark = LocalMainViewModel.current.state.value.absoluteDark
|
||||||
|
val surfaceDarker = 3f
|
||||||
|
val surfaceContainerDarker = if (absoluteDark) 3f else 1.95f
|
||||||
|
|
||||||
return initialTheme.copy(
|
return initialTheme.copy(
|
||||||
surface = initialTheme.surface.copy {
|
surface = initialTheme.surface.copy {
|
||||||
val darker = 3f
|
if (absoluteDark) {
|
||||||
it.copy(
|
return@copy Color.Black
|
||||||
red = it.red / darker,
|
}
|
||||||
green = it.green / darker,
|
|
||||||
blue = it.blue / darker
|
it.darkenBy(surfaceDarker)
|
||||||
)
|
|
||||||
},
|
|
||||||
surfaceContainer = initialTheme.surfaceContainer.copy {
|
|
||||||
val darker = 1.95f
|
|
||||||
it.copy(
|
|
||||||
red = it.red / darker,
|
|
||||||
green = it.green / darker,
|
|
||||||
blue = it.blue / darker
|
|
||||||
)
|
|
||||||
},
|
|
||||||
surfaceContainerLowest = initialTheme.surfaceContainerLowest.copy {
|
|
||||||
val darker = 1.95f
|
|
||||||
it.copy(
|
|
||||||
red = it.red / darker,
|
|
||||||
green = it.green / darker,
|
|
||||||
blue = it.blue / darker
|
|
||||||
)
|
|
||||||
},
|
|
||||||
surfaceContainerLow = initialTheme.surfaceContainerLow.copy {
|
|
||||||
val darker = 1.95f
|
|
||||||
it.copy(
|
|
||||||
red = it.red / darker,
|
|
||||||
green = it.green / darker,
|
|
||||||
blue = it.blue / darker
|
|
||||||
)
|
|
||||||
},
|
|
||||||
surfaceContainerHigh = initialTheme.surfaceContainerHigh.copy {
|
|
||||||
val darker = 1.95f
|
|
||||||
it.copy(
|
|
||||||
red = it.red / darker,
|
|
||||||
green = it.green / darker,
|
|
||||||
blue = it.blue / darker
|
|
||||||
)
|
|
||||||
},
|
|
||||||
surfaceContainerHighest = initialTheme.surfaceContainerHighest.copy {
|
|
||||||
val darker = 1.95f
|
|
||||||
it.copy(
|
|
||||||
red = it.red / darker,
|
|
||||||
green = it.green / darker,
|
|
||||||
blue = it.blue / darker
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
|
surfaceContainer = initialTheme.surfaceContainer.darkenBy(
|
||||||
|
surfaceContainerDarker
|
||||||
|
),
|
||||||
|
surfaceContainerLowest = initialTheme.surfaceContainerLowest.darkenBy(
|
||||||
|
surfaceContainerDarker
|
||||||
|
),
|
||||||
|
surfaceContainerLow = initialTheme.surfaceContainerLow.darkenBy(
|
||||||
|
surfaceContainerDarker
|
||||||
|
),
|
||||||
|
surfaceContainerHigh = initialTheme.surfaceContainerHigh.darkenBy(
|
||||||
|
surfaceContainerDarker
|
||||||
|
),
|
||||||
|
surfaceContainerHighest = initialTheme.surfaceContainerHighest.darkenBy(
|
||||||
|
surfaceContainerDarker
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Color.copy(calculation: (Color) -> Color): Color {
|
private fun Color.copy(calculation: (Color) -> Color): Color {
|
||||||
return calculation(this)
|
return calculation(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Color.darkenBy(value: Float): Color {
|
||||||
|
return copy(
|
||||||
|
red = red / value,
|
||||||
|
green = green / value,
|
||||||
|
blue = blue / value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -209,6 +209,8 @@
|
||||||
<string name="language_option">Мова застосунка</string>
|
<string name="language_option">Мова застосунка</string>
|
||||||
<string name="dark_theme_option">Темна тема</string>
|
<string name="dark_theme_option">Темна тема</string>
|
||||||
<string name="pure_dark_option">Суцільна темрява (ОЛЕД)</string>
|
<string name="pure_dark_option">Суцільна темрява (ОЛЕД)</string>
|
||||||
|
<string name="absolute_dark_option">Абсолютна темрява</string>
|
||||||
|
<string name="absolute_dark_option_desc">Змініть колір фона на повністю чорний</string>
|
||||||
<string name="theme_contrast_option">Контрастність теми</string>
|
<string name="theme_contrast_option">Контрастність теми</string>
|
||||||
<string name="app_theme_option">Тема застосунка</string>
|
<string name="app_theme_option">Тема застосунка</string>
|
||||||
<string name="check_for_updates_option">Перевіряти на оновлення</string>
|
<string name="check_for_updates_option">Перевіряти на оновлення</string>
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,8 @@
|
||||||
<string name="language_option">App language</string>
|
<string name="language_option">App language</string>
|
||||||
<string name="dark_theme_option">Dark theme</string>
|
<string name="dark_theme_option">Dark theme</string>
|
||||||
<string name="pure_dark_option">Pure dark (OLED)</string>
|
<string name="pure_dark_option">Pure dark (OLED)</string>
|
||||||
|
<string name="absolute_dark_option">Absolute dark</string>
|
||||||
|
<string name="absolute_dark_option_desc">Change background color to be completely black</string>
|
||||||
<string name="theme_contrast_option">Theme contrast</string>
|
<string name="theme_contrast_option">Theme contrast</string>
|
||||||
<string name="app_theme_option">App theme</string>
|
<string name="app_theme_option">App theme</string>
|
||||||
<string name="check_for_updates_option">Check for updates</string>
|
<string name="check_for_updates_option">Check for updates</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue