From 63bb317865a2b416434bbad1f0eeae237a1caac4 Mon Sep 17 00:00:00 2001 From: Acclorite <140836141+Acclorite@users.noreply.github.com> Date: Wed, 4 Sep 2024 21:45:07 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Absolute=20Dark=20setting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 --- .../core/constants/DataStoreConstants.kt | 1 + .../book_story/presentation/data/MainEvent.kt | 1 + .../book_story/presentation/data/MainState.kt | 5 ++ .../presentation/data/MainViewModel.kt | 14 ++++ .../settings/AbsoluteDarkSetting.kt | 37 +++++++++ .../ThemePreferencesSubcategory.kt | 5 ++ .../presentation/ui/theme/BlackTheme.kt | 79 ++++++++----------- app/src/main/res/values-uk/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 9 files changed, 100 insertions(+), 46 deletions(-) create mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/AbsoluteDarkSetting.kt diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/core/constants/DataStoreConstants.kt b/app/src/main/java/ua/acclorite/book_story/presentation/core/constants/DataStoreConstants.kt index 21f36f90..603bda06 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/core/constants/DataStoreConstants.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/core/constants/DataStoreConstants.kt @@ -11,6 +11,7 @@ object DataStoreConstants { val THEME = stringPreferencesKey("theme") val DARK_THEME = stringPreferencesKey("dark_theme") val PURE_DARK = stringPreferencesKey("pure_dark") + val ABSOLUTE_DARK = booleanPreferencesKey("absolute_dark") val THEME_CONTRAST = stringPreferencesKey("theme_contrast") val SHOW_START_SCREEN = booleanPreferencesKey("guide") val CHECK_FOR_UPDATES = booleanPreferencesKey("check_for_updates") diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainEvent.kt index a260b95d..9a374852 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainEvent.kt @@ -31,4 +31,5 @@ sealed class MainEvent { data class OnChangeTextAlignment(val alignment: String) : MainEvent() data class OnChangeDoublePressExit(val bool: Boolean) : MainEvent() data class OnChangeLetterSpacing(val spacing: Int) : MainEvent() + data class OnChangeAbsoluteDark(val bool: Boolean) : MainEvent() } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt index 68dfdb12..8604b982 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt @@ -51,6 +51,7 @@ data class MainState( }, val darkTheme: DarkTheme = provideDefaultValue { DarkTheme.FOLLOW_SYSTEM }, val pureDark: PureDark = provideDefaultValue { PureDark.OFF }, + val absoluteDark: Boolean = provideDefaultValue { false }, val themeContrast: ThemeContrast = provideDefaultValue { ThemeContrast.STANDARD }, val showStartScreen: Boolean = provideDefaultValue { true }, val checkForUpdates: Boolean = provideDefaultValue { false }, @@ -118,6 +119,10 @@ data class MainState( PURE_DARK, convert = { toPureDark() } ) { pureDark }, + absoluteDark = provideValue( + ABSOLUTE_DARK + ) { absoluteDark }, + themeContrast = provideValue( THEME_CONTRAST, convert = { toThemeContrast() } ) { themeContrast }, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt index 75411e15..71188e7e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt @@ -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 + ) + } + } + } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/AbsoluteDarkSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/AbsoluteDarkSetting.kt new file mode 100644 index 00000000..379ddb90 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/AbsoluteDarkSetting.kt @@ -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 + ) + ) + } + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ThemePreferencesSubcategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ThemePreferencesSubcategory.kt index 6a3d3095..c8ced355 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ThemePreferencesSubcategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ThemePreferencesSubcategory.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R 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.PureDarkSetting import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.ThemeContrastSetting @@ -66,6 +67,10 @@ fun LazyListScope.ThemePreferencesSubcategory( PureDarkSetting() } + item { + AbsoluteDarkSetting() + } + item { Spacer( modifier = Modifier.height(bottomPadding) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/BlackTheme.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/BlackTheme.kt index 883dcdd6..bd02b164 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/BlackTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/BlackTheme.kt @@ -3,61 +3,48 @@ package ua.acclorite.book_story.presentation.ui.theme import androidx.compose.material3.ColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color +import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel @Composable 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( surface = initialTheme.surface.copy { - val darker = 3f - it.copy( - red = it.red / darker, - green = it.green / darker, - blue = it.blue / darker - ) - }, - 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 - ) + if (absoluteDark) { + return@copy Color.Black + } + + it.darkenBy(surfaceDarker) }, + 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 { return calculation(this) +} + +private fun Color.darkenBy(value: Float): Color { + return copy( + red = red / value, + green = green / value, + blue = blue / value + ) } \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index f6fd677c..fabc2db5 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -209,6 +209,8 @@ Мова застосунка Темна тема Суцільна темрява (ОЛЕД) + Абсолютна темрява + Змініть колір фона на повністю чорний Контрастність теми Тема застосунка Перевіряти на оновлення diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a88e5c67..a7bcf68f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -226,6 +226,8 @@ App language Dark theme Pure dark (OLED) + Absolute dark + Change background color to be completely black Theme contrast App theme Check for updates