🛠️ Reformat Theme (enum)

* Reformatted Theme enum
* More scalable approach, allowing multiple Themes without ThemeContrast
This commit is contained in:
Acclorite 2024-10-24 18:51:28 +03:00
parent a7f2cc6aba
commit aa00a3b088
6 changed files with 50 additions and 74 deletions

View file

@ -1,18 +0,0 @@
package ua.acclorite.book_story.presentation.core.constants
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.ui.Theme
fun Constants.provideThemes() = listOf(
Pair(Theme.DYNAMIC, UIText.StringResource(R.string.dynamic_theme)),
Pair(Theme.BLUE, UIText.StringResource(R.string.blue_theme)),
Pair(Theme.GREEN, UIText.StringResource(R.string.green_theme)),
Pair(Theme.MARSH, UIText.StringResource(R.string.marsh_theme)),
Pair(Theme.RED, UIText.StringResource(R.string.red_theme)),
Pair(Theme.PURPLE, UIText.StringResource(R.string.purple_theme)),
Pair(Theme.LAVENDER, UIText.StringResource(R.string.lavender_theme)),
Pair(Theme.PINK, UIText.StringResource(R.string.pink_theme)),
Pair(Theme.YELLOW, UIText.StringResource(R.string.yellow_theme)),
Pair(Theme.AQUA, UIText.StringResource(R.string.aqua_theme)),
)

View file

@ -2,7 +2,6 @@
package ua.acclorite.book_story.presentation.data package ua.acclorite.book_story.presentation.data
import android.os.Build
import android.os.Parcelable import android.os.Parcelable
import androidx.annotation.Keep import androidx.annotation.Keep
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
@ -49,10 +48,7 @@ data class MainState(
else "en"// Default language. else "en"// Default language.
} }
}, },
val theme: Theme = provideDefaultValue { val theme: Theme = provideDefaultValue { Theme.entries().first() },
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Theme.DYNAMIC
else Theme.BLUE
},
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 absoluteDark: Boolean = provideDefaultValue { false },

View file

@ -14,7 +14,6 @@ import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.ui.BookStoryTheme import ua.acclorite.book_story.presentation.ui.BookStoryTheme
import ua.acclorite.book_story.presentation.ui.ExpandingTransition import ua.acclorite.book_story.presentation.ui.ExpandingTransition
import ua.acclorite.book_story.presentation.ui.Theme
import ua.acclorite.book_story.presentation.ui.ThemeContrast import ua.acclorite.book_story.presentation.ui.ThemeContrast
import ua.acclorite.book_story.presentation.ui.isDark import ua.acclorite.book_story.presentation.ui.isDark
import ua.acclorite.book_story.presentation.ui.isPureDark import ua.acclorite.book_story.presentation.ui.isPureDark
@ -31,7 +30,7 @@ fun ThemeContrastSetting() {
val themeContrastTheme = remember { mutableStateOf(state.value.theme) } val themeContrastTheme = remember { mutableStateOf(state.value.theme) }
LaunchedEffect(state.value.theme) { LaunchedEffect(state.value.theme) {
if (themeContrastTheme.value != state.value.theme && state.value.theme != Theme.DYNAMIC) { if (state.value.theme.hasThemeContrast) {
themeContrastTheme.value = state.value.theme themeContrastTheme.value = state.value.theme
} }
} }
@ -42,10 +41,10 @@ fun ThemeContrastSetting() {
isPureDark = state.value.pureDark.isPureDark(context = LocalContext.current), isPureDark = state.value.pureDark.isPureDark(context = LocalContext.current),
themeContrast = state.value.themeContrast themeContrast = state.value.themeContrast
) { ) {
ExpandingTransition(visible = state.value.theme != Theme.DYNAMIC) { ExpandingTransition(visible = state.value.theme.hasThemeContrast) {
SegmentedButtonWithTitle( SegmentedButtonWithTitle(
title = stringResource(id = R.string.theme_contrast_option), title = stringResource(id = R.string.theme_contrast_option),
enabled = state.value.theme != Theme.DYNAMIC, enabled = state.value.theme.hasThemeContrast,
buttons = ThemeContrast.entries.map { buttons = ThemeContrast.entries.map {
ButtonItem( ButtonItem(
id = it.toString(), id = it.toString(),

View file

@ -1,6 +1,5 @@
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings
import android.os.Build
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
@ -11,6 +10,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -19,7 +19,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@ -28,7 +28,6 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@ -38,10 +37,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
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.domain.util.UIText
import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideThemes
import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryTitle import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryTitle
@ -53,7 +49,7 @@ import ua.acclorite.book_story.presentation.ui.isPureDark
/** /**
* Theme setting. * Theme setting.
* Lets user change app's theme from available in [provideThemes]. * Lets user change app's theme from available in [Theme.entries].
*/ */
@Composable @Composable
fun ThemeSetting( fun ThemeSetting(
@ -63,11 +59,6 @@ fun ThemeSetting(
val state = MainViewModel.getState() val state = MainViewModel.getState()
val onMainEvent = MainViewModel.getEvent() val onMainEvent = MainViewModel.getEvent()
val themes = remember {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Constants.provideThemes()
else Constants.provideThemes().dropWhile { it.first == Theme.DYNAMIC }
}
Column( Column(
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
@ -80,28 +71,21 @@ fun ThemeSetting(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
LazyRow( LazyRow(
Modifier.fillMaxWidth(), Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp) horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(horizontal = horizontalPadding)
) { ) {
itemsIndexed( items(
themes, Theme.entries(),
key = { _, themeEntry -> themeEntry.first.name } key = { theme -> theme.name }
) { index, themeEntry -> ) { theme ->
if (index == 0) {
Spacer(modifier = Modifier.width(horizontalPadding))
}
ThemeSettingItem( ThemeSettingItem(
theme = themeEntry, theme = theme,
darkTheme = state.value.darkTheme.isDark(), darkTheme = state.value.darkTheme.isDark(),
themeContrast = state.value.themeContrast, themeContrast = state.value.themeContrast,
isPureDark = state.value.pureDark.isPureDark(context = LocalContext.current), isPureDark = state.value.pureDark.isPureDark(context = LocalContext.current),
selected = state.value.theme == themeEntry.first selected = state.value.theme == theme
) { ) {
onMainEvent(MainEvent.OnChangeTheme(themeEntry.first.toString())) onMainEvent(MainEvent.OnChangeTheme(theme.name))
}
if (index == themes.lastIndex) {
Spacer(modifier = Modifier.width(horizontalPadding))
} }
} }
} }
@ -121,7 +105,7 @@ fun ThemeSetting(
*/ */
@Composable @Composable
private fun ThemeSettingItem( private fun ThemeSettingItem(
theme: Pair<Theme, UIText>, theme: Theme,
darkTheme: Boolean, darkTheme: Boolean,
isPureDark: Boolean, isPureDark: Boolean,
themeContrast: ThemeContrast, themeContrast: ThemeContrast,
@ -129,10 +113,10 @@ private fun ThemeSettingItem(
onClick: () -> Unit onClick: () -> Unit
) { ) {
val colorScheme = animatedColorScheme( val colorScheme = animatedColorScheme(
theme.first, theme = theme,
darkTheme, isDark = darkTheme,
isPureDark, isPureDark = isPureDark,
themeContrast themeContrast = themeContrast
) )
Column( Column(
@ -227,7 +211,7 @@ private fun ThemeSettingItem(
} }
Spacer(modifier = Modifier.height(6.dp)) Spacer(modifier = Modifier.height(6.dp))
Text( Text(
text = theme.second.asString(), text = stringResource(id = theme.title),
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,

View file

@ -1,8 +1,11 @@
package ua.acclorite.book_story.presentation.ui package ua.acclorite.book_story.presentation.ui
import android.os.Build
import androidx.annotation.StringRes
import androidx.compose.material3.ColorScheme import androidx.compose.material3.ColorScheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.ui.theme.aquaTheme import ua.acclorite.book_story.presentation.ui.theme.aquaTheme
import ua.acclorite.book_story.presentation.ui.theme.blackTheme import ua.acclorite.book_story.presentation.ui.theme.blackTheme
import ua.acclorite.book_story.presentation.ui.theme.blueTheme import ua.acclorite.book_story.presentation.ui.theme.blueTheme
@ -15,18 +18,31 @@ import ua.acclorite.book_story.presentation.ui.theme.purpleTheme
import ua.acclorite.book_story.presentation.ui.theme.redTheme import ua.acclorite.book_story.presentation.ui.theme.redTheme
import ua.acclorite.book_story.presentation.ui.theme.yellowTheme import ua.acclorite.book_story.presentation.ui.theme.yellowTheme
@Immutable @Immutable
enum class Theme { enum class Theme(
DYNAMIC, val hasThemeContrast: Boolean,
BLUE, @StringRes val title: Int
GREEN, ) {
RED, DYNAMIC(hasThemeContrast = false, title = R.string.dynamic_theme),
PURPLE, BLUE(hasThemeContrast = true, title = R.string.blue_theme),
PINK, GREEN(hasThemeContrast = true, title = R.string.green_theme),
YELLOW, MARSH(hasThemeContrast = true, title = R.string.marsh_theme),
AQUA, RED(hasThemeContrast = true, title = R.string.red_theme),
MARSH, PURPLE(hasThemeContrast = true, title = R.string.purple_theme),
LAVENDER, LAVENDER(hasThemeContrast = true, title = R.string.lavender_theme),
PINK(hasThemeContrast = false, title = R.string.pink_theme),
YELLOW(hasThemeContrast = true, title = R.string.yellow_theme),
AQUA(hasThemeContrast = true, title = R.string.aqua_theme);
companion object {
fun entries(): List<Theme> {
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> Theme.entries
else -> Theme.entries.dropWhile { it == DYNAMIC }
}
}
}
} }
/** /**

View file

@ -113,8 +113,7 @@ fun BookStoryTheme(
} }
val colorScheme = colorScheme( val colorScheme = colorScheme(
theme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) theme theme = Theme.entries().find { it == theme } ?: Theme.BLUE,
else if (theme != Theme.DYNAMIC) theme else Theme.BLUE,
darkTheme = isDark, darkTheme = isDark,
isPureDark = isPureDark, isPureDark = isPureDark,
themeContrast = themeContrast themeContrast = themeContrast