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