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