Changed SettingsScreen structure. (more scalable way)
This commit is contained in:
parent
3aefb37935
commit
0665ff62e9
31 changed files with 1338 additions and 940 deletions
|
|
@ -4,10 +4,8 @@ import androidx.activity.ComponentActivity
|
|||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
|
|
@ -23,21 +21,13 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.domain.util.Constants
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.components.CustomBottomSheet
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.ColorPickerWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ColorsSubcategory
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.ReaderSettingsCategory
|
||||
|
||||
/**
|
||||
* Settings bottom sheet. Has General and Colors categories.
|
||||
|
|
@ -57,12 +47,6 @@ fun ReaderSettingsBottomSheet(
|
|||
val currentPage by remember { derivedStateOf { pagerState.currentPage } }
|
||||
val context = LocalContext.current
|
||||
|
||||
val fontFamily = remember(mainState.value.fontFamily) {
|
||||
Constants.FONTS.find {
|
||||
it.id == mainState.value.fontFamily
|
||||
} ?: Constants.FONTS[0]
|
||||
}
|
||||
|
||||
val scrimColor = if (currentPage == 1) Color.Transparent
|
||||
else BottomSheetDefaults.ScrimColor
|
||||
|
||||
|
|
@ -109,213 +93,24 @@ fun ReaderSettingsBottomSheet(
|
|||
HorizontalPager(state = pagerState) { page ->
|
||||
LazyColumn {
|
||||
if (page == 0) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(22.dp))
|
||||
}
|
||||
item {
|
||||
CategoryTitle(
|
||||
title = stringResource(id = R.string.font_reader_settings),
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
item {
|
||||
ChipsWithTitle(
|
||||
title = stringResource(id = R.string.font_family_option),
|
||||
chips = Constants.FONTS
|
||||
.map {
|
||||
ButtonItem(
|
||||
it.id,
|
||||
it.fontName.asString(),
|
||||
MaterialTheme.typography.labelLarge.copy(
|
||||
fontFamily = it.font
|
||||
),
|
||||
it.id == fontFamily.id
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
onMainEvent(MainEvent.OnChangeFontFamily(it.id))
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
ChipsWithTitle(
|
||||
title = stringResource(id = R.string.font_style_option),
|
||||
chips = listOf(
|
||||
ButtonItem(
|
||||
"normal",
|
||||
stringResource(id = R.string.font_style_normal),
|
||||
MaterialTheme.typography.labelLarge.copy(
|
||||
fontFamily = fontFamily.font,
|
||||
fontStyle = FontStyle.Normal
|
||||
),
|
||||
!mainState.value.isItalic!!
|
||||
),
|
||||
ButtonItem(
|
||||
"italic",
|
||||
stringResource(id = R.string.font_style_italic),
|
||||
MaterialTheme.typography.labelLarge.copy(
|
||||
fontFamily = fontFamily.font,
|
||||
fontStyle = FontStyle.Italic
|
||||
),
|
||||
mainState.value.isItalic!!
|
||||
),
|
||||
),
|
||||
onClick = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeFontStyle(
|
||||
when (it.id) {
|
||||
"italic" -> true
|
||||
else -> false
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
SliderWithTitle(
|
||||
value = mainState.value.fontSize!! to "pt",
|
||||
fromValue = 10,
|
||||
toValue = 35,
|
||||
title = stringResource(id = R.string.font_size_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeFontSize(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(22.dp))
|
||||
}
|
||||
item {
|
||||
CategoryTitle(
|
||||
title = stringResource(id = R.string.text_reader_settings),
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
item {
|
||||
SliderWithTitle(
|
||||
value = mainState.value.sidePadding!! to "pt",
|
||||
fromValue = 1,
|
||||
toValue = 20,
|
||||
title = stringResource(id = R.string.side_padding_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeSidePadding(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
SliderWithTitle(
|
||||
value = mainState.value.lineHeight!! to "pt",
|
||||
fromValue = 1,
|
||||
toValue = 16,
|
||||
title = stringResource(id = R.string.line_height_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeLineHeight(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
SliderWithTitle(
|
||||
value = mainState.value.paragraphHeight!! to "pt",
|
||||
fromValue = 0,
|
||||
toValue = 24,
|
||||
title = stringResource(id = R.string.paragraph_height_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeParagraphHeight(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
SwitchWithTitle(
|
||||
selected = mainState.value.paragraphIndentation!!,
|
||||
title = stringResource(id = R.string.paragraph_indentation_option)
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeParagraphIndentation(!mainState.value.paragraphIndentation!!)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(22.dp))
|
||||
}
|
||||
item {
|
||||
CategoryTitle(
|
||||
title = stringResource(id = R.string.translator_reader_settings),
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
|
||||
item {
|
||||
SwitchWithTitle(
|
||||
selected = mainState.value.doubleClickTranslation!!,
|
||||
title = stringResource(id = R.string.translator_double_click_to_translate_option),
|
||||
description = stringResource(id = R.string.translator_double_click_to_translate_option_desc),
|
||||
onClick = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeDoubleClickTranslation(
|
||||
!mainState.value.doubleClickTranslation!!
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
ReaderSettingsCategory(
|
||||
state = mainState,
|
||||
onMainEvent = onMainEvent,
|
||||
titleColor = { MaterialTheme.colorScheme.onSurface },
|
||||
topPadding = 16.dp,
|
||||
bottomPadding = 8.dp + it
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
LazyColumn {
|
||||
if (page == 1) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(14.dp))
|
||||
}
|
||||
item {
|
||||
ColorPickerWithTitle(
|
||||
value = Color(mainState.value.backgroundColor!!.toULong()),
|
||||
title = stringResource(id = R.string.background_color_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeBackgroundColor(
|
||||
it.value.toLong()
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
ColorPickerWithTitle(
|
||||
value = Color(mainState.value.fontColor!!.toULong()),
|
||||
title = stringResource(id = R.string.font_color_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeFontColor(
|
||||
it.value.toLong()
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier.height(
|
||||
8.dp + it
|
||||
)
|
||||
ColorsSubcategory(
|
||||
state = mainState,
|
||||
onMainEvent = onMainEvent,
|
||||
showTitle = false,
|
||||
topPadding = 16.dp,
|
||||
bottomPadding = 8.dp + it
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import ua.acclorite.book_story.presentation.components.CategoryTitle
|
|||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun ChipsWithTitle(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String,
|
||||
chips: List<ButtonItem>,
|
||||
horizontalPadding: Dp = 18.dp,
|
||||
|
|
@ -30,7 +31,7 @@ fun ChipsWithTitle(
|
|||
onClick: (ButtonItem) -> Unit
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = horizontalPadding, vertical = verticalPadding)
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import androidx.compose.ui.unit.dp
|
|||
*/
|
||||
@Composable
|
||||
fun SwitchWithTitle(
|
||||
modifier: Modifier = Modifier,
|
||||
selected: Boolean,
|
||||
title: String,
|
||||
description: String? = null,
|
||||
|
|
@ -38,7 +39,7 @@ fun SwitchWithTitle(
|
|||
onClick: () -> Unit
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.clickable { onClick() }
|
||||
.padding(horizontal = horizontalPadding, vertical = verticalPadding),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
|
|
@ -15,39 +13,21 @@ import androidx.compose.material3.Scaffold
|
|||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.domain.util.OnNavigate
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.components.GoBackButton
|
||||
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
|
||||
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.ColorPickerWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.theme_switcher.AppearanceSettingsThemeSwitcher
|
||||
import ua.acclorite.book_story.presentation.ui.BookStoryTheme
|
||||
import ua.acclorite.book_story.presentation.ui.DarkTheme
|
||||
import ua.acclorite.book_story.presentation.ui.PureDark
|
||||
import ua.acclorite.book_story.presentation.ui.SlidingTransition
|
||||
import ua.acclorite.book_story.presentation.ui.Theme
|
||||
import ua.acclorite.book_story.presentation.ui.ThemeContrast
|
||||
import ua.acclorite.book_story.presentation.ui.isDark
|
||||
import ua.acclorite.book_story.presentation.ui.isPureDark
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.AppearanceSettingsCategory
|
||||
|
||||
@Composable
|
||||
fun AppearanceSettingsRoot() {
|
||||
|
|
@ -71,13 +51,6 @@ private fun AppearanceSettings(
|
|||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||
val themeContrastTheme = remember { mutableStateOf(state.value.theme!!) }
|
||||
|
||||
LaunchedEffect(state.value.theme) {
|
||||
if (themeContrastTheme.value != state.value.theme && state.value.theme != Theme.DYNAMIC) {
|
||||
themeContrastTheme.value = state.value.theme!!
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
Modifier
|
||||
|
|
@ -107,189 +80,10 @@ private fun AppearanceSettings(
|
|||
.padding(top = paddingValues.calculateTopPadding()),
|
||||
state = scrollState.second
|
||||
) {
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(16.dp)
|
||||
)
|
||||
}
|
||||
item {
|
||||
CategoryTitle(
|
||||
modifier = Modifier.animateItem(),
|
||||
title = stringResource(id = R.string.theme_appearance_settings),
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
SegmentedButtonWithTitle(
|
||||
modifier = Modifier.animateItem(),
|
||||
title = stringResource(id = R.string.dark_theme_option),
|
||||
locked = true,
|
||||
buttons = DarkTheme.entries.map {
|
||||
ButtonItem(
|
||||
it.toString(),
|
||||
when (it) {
|
||||
DarkTheme.OFF -> stringResource(id = R.string.dark_theme_off)
|
||||
DarkTheme.ON -> stringResource(id = R.string.dark_theme_on)
|
||||
DarkTheme.FOLLOW_SYSTEM -> stringResource(id = R.string.dark_theme_follow_system)
|
||||
},
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it == state.value.darkTheme
|
||||
)
|
||||
}
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeDarkTheme(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
AppearanceSettingsThemeSwitcher(
|
||||
modifier = Modifier.animateItem(),
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BookStoryTheme(
|
||||
theme = themeContrastTheme.value,
|
||||
isDark = state.value.darkTheme!!.isDark(),
|
||||
isPureDark = state.value.pureDark!!.isPureDark(context = LocalContext.current),
|
||||
themeContrast = state.value.themeContrast!!
|
||||
) {
|
||||
SlidingTransition(
|
||||
modifier = Modifier.animateItem(
|
||||
fadeInSpec = null,
|
||||
fadeOutSpec = null
|
||||
),
|
||||
visible = state.value.theme != Theme.DYNAMIC,
|
||||
) {
|
||||
SegmentedButtonWithTitle(
|
||||
title = stringResource(id = R.string.theme_contrast_option),
|
||||
locked = state.value.theme != Theme.DYNAMIC,
|
||||
buttons = ThemeContrast.entries.map {
|
||||
ButtonItem(
|
||||
it.toString(),
|
||||
when (it) {
|
||||
ThemeContrast.STANDARD -> stringResource(id = R.string.theme_contrast_standard)
|
||||
ThemeContrast.MEDIUM -> stringResource(id = R.string.theme_contrast_medium)
|
||||
ThemeContrast.HIGH -> stringResource(id = R.string.theme_contrast_high)
|
||||
},
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it == state.value.themeContrast
|
||||
)
|
||||
}
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeThemeContrast(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
SlidingTransition(
|
||||
modifier = Modifier.animateItem(
|
||||
fadeInSpec = null,
|
||||
fadeOutSpec = null
|
||||
),
|
||||
visible = state.value.darkTheme!!.isDark(),
|
||||
) {
|
||||
SegmentedButtonWithTitle(
|
||||
title = stringResource(id = R.string.pure_dark_option),
|
||||
locked = true,
|
||||
buttons = PureDark.entries.map {
|
||||
ButtonItem(
|
||||
it.toString(),
|
||||
when (it) {
|
||||
PureDark.OFF -> stringResource(id = R.string.pure_dark_off)
|
||||
PureDark.ON -> stringResource(id = R.string.pure_dark_on)
|
||||
PureDark.SAVER -> stringResource(id = R.string.pure_dark_power_saver)
|
||||
},
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it == state.value.pureDark
|
||||
)
|
||||
}
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangePureDark(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(22.dp)
|
||||
)
|
||||
CategoryTitle(
|
||||
title = stringResource(id = R.string.colors_appearance_settings),
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.animateItem()
|
||||
)
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
ColorPickerWithTitle(
|
||||
modifier = Modifier.animateItem(),
|
||||
value = Color(state.value.backgroundColor!!.toULong()),
|
||||
title = stringResource(id = R.string.background_color_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeBackgroundColor(
|
||||
it.value.toLong()
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
ColorPickerWithTitle(
|
||||
modifier = Modifier.animateItem(),
|
||||
value = Color(state.value.fontColor!!.toULong()),
|
||||
title = stringResource(id = R.string.font_color_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeFontColor(
|
||||
it.value.toLong()
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(48.dp)
|
||||
)
|
||||
}
|
||||
AppearanceSettingsCategory(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
@file:Suppress("FunctionName")
|
||||
|
||||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ColorsSubcategory
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ThemePreferencesSubcategory
|
||||
|
||||
/**
|
||||
* Appearance Settings Category.
|
||||
* Contains all Appearance settings such as Theme.
|
||||
*
|
||||
* @param state [MainState] instance.
|
||||
* @param onMainEvent [MainEvent] callback.
|
||||
* @param titleColor Title's color.
|
||||
* @param topPadding Top padding to be applied.
|
||||
* @param bottomPadding Bottom padding to be applied.
|
||||
*/
|
||||
fun LazyListScope.AppearanceSettingsCategory(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||
topPadding: Dp = 16.dp,
|
||||
bottomPadding: Dp = 48.dp
|
||||
) {
|
||||
ThemePreferencesSubcategory(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent,
|
||||
titleColor = titleColor,
|
||||
topPadding = topPadding,
|
||||
bottomPadding = 0.dp
|
||||
)
|
||||
ColorsSubcategory(
|
||||
state,
|
||||
onMainEvent = onMainEvent,
|
||||
titleColor = titleColor,
|
||||
topPadding = 22.dp,
|
||||
bottomPadding = bottomPadding
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||
import ua.acclorite.book_story.presentation.ui.DarkTheme
|
||||
|
||||
/**
|
||||
* Dark Theme setting.
|
||||
* If true, dark theme applied to the app's theme.
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.DarkThemeSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
SegmentedButtonWithTitle(
|
||||
title = stringResource(id = R.string.dark_theme_option),
|
||||
modifier = Modifier.animateItem(),
|
||||
locked = true,
|
||||
buttons = DarkTheme.entries.map {
|
||||
ButtonItem(
|
||||
it.toString(),
|
||||
when (it) {
|
||||
DarkTheme.OFF -> stringResource(id = R.string.dark_theme_off)
|
||||
DarkTheme.ON -> stringResource(id = R.string.dark_theme_on)
|
||||
DarkTheme.FOLLOW_SYSTEM -> stringResource(id = R.string.dark_theme_follow_system)
|
||||
},
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it == state.value.darkTheme
|
||||
)
|
||||
}
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeDarkTheme(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||
import ua.acclorite.book_story.presentation.ui.PureDark
|
||||
import ua.acclorite.book_story.presentation.ui.SlidingTransition
|
||||
import ua.acclorite.book_story.presentation.ui.isDark
|
||||
|
||||
/**
|
||||
* Pure Dark setting.
|
||||
* If true, enables Pure Dark (OLED) theme.
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.PureDarkSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
SlidingTransition(
|
||||
modifier = Modifier.animateItem(
|
||||
fadeInSpec = null,
|
||||
fadeOutSpec = null
|
||||
),
|
||||
visible = state.value.darkTheme!!.isDark(),
|
||||
) {
|
||||
SegmentedButtonWithTitle(
|
||||
title = stringResource(id = R.string.pure_dark_option),
|
||||
locked = true,
|
||||
buttons = PureDark.entries.map {
|
||||
ButtonItem(
|
||||
it.toString(),
|
||||
when (it) {
|
||||
PureDark.OFF -> stringResource(id = R.string.pure_dark_off)
|
||||
PureDark.ON -> stringResource(id = R.string.pure_dark_on)
|
||||
PureDark.SAVER -> stringResource(id = R.string.pure_dark_power_saver)
|
||||
},
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it == state.value.pureDark
|
||||
)
|
||||
}
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangePureDark(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||
import ua.acclorite.book_story.presentation.ui.BookStoryTheme
|
||||
import ua.acclorite.book_story.presentation.ui.SlidingTransition
|
||||
import ua.acclorite.book_story.presentation.ui.Theme
|
||||
import ua.acclorite.book_story.presentation.ui.ThemeContrast
|
||||
import ua.acclorite.book_story.presentation.ui.isDark
|
||||
import ua.acclorite.book_story.presentation.ui.isPureDark
|
||||
|
||||
/**
|
||||
* Theme Contrast setting.
|
||||
* Lets user change theme contrast levels.
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.ThemeContrastSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
val themeContrastTheme = remember { mutableStateOf(state.value.theme!!) }
|
||||
|
||||
LaunchedEffect(state.value.theme) {
|
||||
if (themeContrastTheme.value != state.value.theme && state.value.theme != Theme.DYNAMIC) {
|
||||
themeContrastTheme.value = state.value.theme!!
|
||||
}
|
||||
}
|
||||
|
||||
BookStoryTheme(
|
||||
theme = themeContrastTheme.value,
|
||||
isDark = state.value.darkTheme!!.isDark(),
|
||||
isPureDark = state.value.pureDark!!.isPureDark(context = LocalContext.current),
|
||||
themeContrast = state.value.themeContrast!!
|
||||
) {
|
||||
SlidingTransition(
|
||||
modifier = Modifier.animateItem(
|
||||
fadeInSpec = null,
|
||||
fadeOutSpec = null
|
||||
),
|
||||
visible = state.value.theme != Theme.DYNAMIC,
|
||||
) {
|
||||
SegmentedButtonWithTitle(
|
||||
title = stringResource(id = R.string.theme_contrast_option),
|
||||
locked = state.value.theme != Theme.DYNAMIC,
|
||||
buttons = ThemeContrast.entries.map {
|
||||
ButtonItem(
|
||||
it.toString(),
|
||||
when (it) {
|
||||
ThemeContrast.STANDARD -> stringResource(id = R.string.theme_contrast_standard)
|
||||
ThemeContrast.MEDIUM -> stringResource(id = R.string.theme_contrast_medium)
|
||||
ThemeContrast.HIGH -> stringResource(id = R.string.theme_contrast_high)
|
||||
},
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it == state.value.themeContrast
|
||||
)
|
||||
}
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeThemeContrast(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.theme_switcher
|
||||
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.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
|
|
@ -10,6 +11,7 @@ import androidx.compose.foundation.clickable
|
|||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
|
@ -17,6 +19,8 @@ import androidx.compose.foundation.layout.height
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
|
@ -25,21 +29,80 @@ import androidx.compose.material3.Icon
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.util.Constants
|
||||
import ua.acclorite.book_story.domain.util.UIText
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility
|
||||
import ua.acclorite.book_story.presentation.components.customItems
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.ui.Theme
|
||||
import ua.acclorite.book_story.presentation.ui.ThemeContrast
|
||||
import ua.acclorite.book_story.presentation.ui.animatedColorScheme
|
||||
import ua.acclorite.book_story.presentation.ui.isDark
|
||||
import ua.acclorite.book_story.presentation.ui.isPureDark
|
||||
|
||||
/**
|
||||
* Theme switcher item. Used to change app theme.
|
||||
* Theme setting.
|
||||
* Lets user change app's theme from available in [Constants.THEMES].
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.ThemeSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
verticalPadding: Dp = 8.dp,
|
||||
horizontalPadding: Dp = 18.dp
|
||||
) {
|
||||
val themes = remember {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Constants.THEMES
|
||||
else Constants.THEMES.dropWhile { it.first == Theme.DYNAMIC }
|
||||
}
|
||||
|
||||
Column(
|
||||
Modifier
|
||||
.animateItem()
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = verticalPadding)
|
||||
) {
|
||||
CategoryTitle(
|
||||
title = stringResource(id = R.string.app_theme_option),
|
||||
padding = horizontalPadding
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
LazyRow(
|
||||
Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
contentPadding = PaddingValues(horizontal = horizontalPadding)
|
||||
) {
|
||||
customItems(themes, key = { it.first.name }) { themeEntry ->
|
||||
ThemeSettingItem(
|
||||
theme = themeEntry,
|
||||
darkTheme = state.value.darkTheme!!.isDark(),
|
||||
themeContrast = state.value.themeContrast!!,
|
||||
isPureDark = state.value.pureDark!!.isPureDark(context = LocalContext.current),
|
||||
selected = state.value.theme == themeEntry.first
|
||||
) {
|
||||
onMainEvent(MainEvent.OnChangeTheme(themeEntry.first.toString()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme Setting item.
|
||||
* Used to switch between different themes.
|
||||
*
|
||||
* @param theme Target [Theme].
|
||||
* @param darkTheme Whether should be shown in Dark Theme.
|
||||
|
|
@ -49,7 +112,7 @@ import ua.acclorite.book_story.presentation.ui.animatedColorScheme
|
|||
* @param onClick OnClick callback.
|
||||
*/
|
||||
@Composable
|
||||
fun AppearanceSettingsThemeSwitcherItem(
|
||||
private fun ThemeSettingItem(
|
||||
theme: Pair<Theme, UIText>,
|
||||
darkTheme: Boolean,
|
||||
isPureDark: Boolean,
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
@file:Suppress("FunctionName")
|
||||
|
||||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.coerceAtLeast
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.ColorPickerWithTitle
|
||||
|
||||
/**
|
||||
* Colors subcategory.
|
||||
* Contains all settings from Colors.
|
||||
*/
|
||||
fun LazyListScope.ColorsSubcategory(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||
title: @Composable () -> String = { stringResource(id = R.string.colors_appearance_settings) },
|
||||
showTitle: Boolean = true,
|
||||
topPadding: Dp,
|
||||
bottomPadding: Dp
|
||||
) {
|
||||
item {
|
||||
if (showTitle) {
|
||||
CategoryTitle(
|
||||
title = title.invoke(),
|
||||
color = titleColor.invoke(),
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.padding(
|
||||
top = topPadding,
|
||||
bottom = 8.dp
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height((topPadding - 8.dp).coerceAtLeast(0.dp))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// todo: This will be replaced with ColorPresets
|
||||
item {
|
||||
ColorPickerWithTitle(
|
||||
modifier = Modifier.animateItem(),
|
||||
value = Color(state.value.backgroundColor!!.toULong()),
|
||||
title = stringResource(id = R.string.background_color_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeBackgroundColor(
|
||||
it.value.toLong()
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
ColorPickerWithTitle(
|
||||
modifier = Modifier.animateItem(),
|
||||
value = Color(state.value.fontColor!!.toULong()),
|
||||
title = stringResource(id = R.string.font_color_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeFontColor(
|
||||
it.value.toLong()
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
// ---------
|
||||
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(bottomPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
@file:Suppress("FunctionName")
|
||||
|
||||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.coerceAtLeast
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
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
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.ThemeSetting
|
||||
|
||||
/**
|
||||
* Theme Preferences subcategory.
|
||||
* Contains all settings from Theme Preferences.
|
||||
*/
|
||||
fun LazyListScope.ThemePreferencesSubcategory(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||
title: @Composable () -> String = { stringResource(id = R.string.theme_appearance_settings) },
|
||||
showTitle: Boolean = true,
|
||||
topPadding: Dp,
|
||||
bottomPadding: Dp
|
||||
) {
|
||||
item {
|
||||
if (showTitle) {
|
||||
CategoryTitle(
|
||||
title = title.invoke(),
|
||||
color = titleColor.invoke(),
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.padding(
|
||||
top = topPadding,
|
||||
bottom = 8.dp
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height((topPadding - 8.dp).coerceAtLeast(0.dp))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
DarkThemeSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
ThemeSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
ThemeContrastSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
PureDarkSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(bottomPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.theme_switcher
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.util.Constants
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.components.customItemsIndexed
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.ui.Theme
|
||||
import ua.acclorite.book_story.presentation.ui.isDark
|
||||
import ua.acclorite.book_story.presentation.ui.isPureDark
|
||||
|
||||
/**
|
||||
* Theme switcher.
|
||||
*/
|
||||
@Composable
|
||||
fun AppearanceSettingsThemeSwitcher(
|
||||
modifier: Modifier = Modifier,
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
verticalPadding: Dp = 8.dp
|
||||
) {
|
||||
val themes = remember {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Constants.THEMES
|
||||
else Constants.THEMES.dropWhile { it.first == Theme.DYNAMIC }
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = verticalPadding)
|
||||
) {
|
||||
CategoryTitle(
|
||||
title = stringResource(id = R.string.app_theme_option)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
LazyRow(
|
||||
Modifier
|
||||
.fillMaxWidth(),
|
||||
) {
|
||||
customItemsIndexed(themes, key = { it.first.name }) { index, themeEntry ->
|
||||
if (index == 0) {
|
||||
Spacer(modifier = Modifier.width(18.dp))
|
||||
} else {
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
}
|
||||
|
||||
AppearanceSettingsThemeSwitcherItem(
|
||||
theme = themeEntry,
|
||||
darkTheme = state.value.darkTheme!!.isDark(),
|
||||
themeContrast = state.value.themeContrast!!,
|
||||
isPureDark = state.value.pureDark!!.isPureDark(context = LocalContext.current),
|
||||
selected = state.value.theme == themeEntry.first
|
||||
) {
|
||||
onMainEvent(MainEvent.OnChangeTheme(themeEntry.first.toString()))
|
||||
}
|
||||
|
||||
if (index == themes.lastIndex) {
|
||||
Spacer(modifier = Modifier.width(18.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,7 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.general
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
|
|
@ -22,15 +17,9 @@ import androidx.compose.runtime.State
|
|||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.domain.util.Constants
|
||||
import ua.acclorite.book_story.domain.util.OnNavigate
|
||||
import ua.acclorite.book_story.presentation.components.GoBackButton
|
||||
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
|
||||
|
|
@ -38,10 +27,9 @@ import ua.acclorite.book_story.presentation.data.LocalNavigator
|
|||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.GeneralSettingsCategory
|
||||
|
||||
@Composable
|
||||
fun GeneralSettingsRoot() {
|
||||
|
|
@ -59,8 +47,8 @@ fun GeneralSettingsRoot() {
|
|||
)
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPermissionsApi::class)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun GeneralSettings(
|
||||
state: State<MainState>,
|
||||
|
|
@ -69,11 +57,6 @@ private fun GeneralSettings(
|
|||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||
val activity = LocalContext.current as ComponentActivity
|
||||
|
||||
val notificationsPermissionState = rememberPermissionState(
|
||||
permission = Manifest.permission.POST_NOTIFICATIONS
|
||||
)
|
||||
|
||||
Scaffold(
|
||||
Modifier
|
||||
|
|
@ -103,53 +86,11 @@ private fun GeneralSettings(
|
|||
.padding(top = paddingValues.calculateTopPadding()),
|
||||
state = scrollState.second
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
item {
|
||||
ChipsWithTitle(
|
||||
title = stringResource(id = R.string.language_option),
|
||||
chips = Constants.LANGUAGES.sortedBy { it.second }.map {
|
||||
ButtonItem(
|
||||
it.first,
|
||||
it.second,
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it.first == state.value.language
|
||||
)
|
||||
}.sortedBy { it.title }
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeLanguage(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
SwitchWithTitle(
|
||||
selected = state.value.checkForUpdates!!,
|
||||
title = stringResource(id = R.string.check_for_updates_option),
|
||||
description = stringResource(id = R.string.check_for_updates_option_desc)
|
||||
) {
|
||||
onSettingsEvent(
|
||||
SettingsEvent.OnGeneralChangeCheckForUpdates(
|
||||
enable = !state.value.checkForUpdates!!,
|
||||
activity = activity,
|
||||
notificationsPermissionState = notificationsPermissionState,
|
||||
onChangeCheckForUpdates = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeCheckForUpdates(
|
||||
it
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item { Spacer(modifier = Modifier.height(48.dp)) }
|
||||
GeneralSettingsCategory(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent,
|
||||
onSettingsEvent = onSettingsEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
@file:Suppress("FunctionName")
|
||||
|
||||
package ua.acclorite.book_story.presentation.screens.settings.nested.general.components
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.coerceAtLeast
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.AppLanguageSetting
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.CheckForUpdatesSetting
|
||||
|
||||
/**
|
||||
* General Settings Category.
|
||||
* Contains all General settings such as App Language.
|
||||
*
|
||||
* @param state [MainState] instance.
|
||||
* @param onMainEvent [MainEvent] callback.
|
||||
* @param onSettingsEvent [SettingsEvent] callback.
|
||||
* @param topPadding Top padding to be applied.
|
||||
* @param bottomPadding Bottom padding to be applied.
|
||||
*/
|
||||
fun LazyListScope.GeneralSettingsCategory(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
onSettingsEvent: (SettingsEvent) -> Unit,
|
||||
topPadding: Dp = 16.dp,
|
||||
bottomPadding: Dp = 48.dp
|
||||
) {
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height((topPadding - 8.dp).coerceAtLeast(0.dp))
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
AppLanguageSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
CheckForUpdatesSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent,
|
||||
onSettingsEvent = onSettingsEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(bottomPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.domain.util.Constants
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
|
||||
|
||||
/**
|
||||
* App Language setting.
|
||||
* Changes app's language.
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.AppLanguageSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
ChipsWithTitle(
|
||||
title = stringResource(id = R.string.language_option),
|
||||
modifier = Modifier.animateItem(),
|
||||
chips = Constants.LANGUAGES.sortedBy { it.second }.map {
|
||||
ButtonItem(
|
||||
it.first,
|
||||
it.second,
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it.first == state.value.language
|
||||
)
|
||||
}.sortedBy { it.title }
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeLanguage(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
||||
|
||||
/**
|
||||
* Check For Updates setting.
|
||||
* If true, checks for the update on app start.
|
||||
*/
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@SuppressLint("InlinedApi")
|
||||
@Composable
|
||||
fun LazyItemScope.CheckForUpdatesSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
onSettingsEvent: (SettingsEvent) -> Unit
|
||||
) {
|
||||
val activity = LocalContext.current as ComponentActivity
|
||||
val notificationsPermissionState = rememberPermissionState(
|
||||
permission = Manifest.permission.POST_NOTIFICATIONS
|
||||
)
|
||||
|
||||
SwitchWithTitle(
|
||||
selected = state.value.checkForUpdates!!,
|
||||
modifier = Modifier.animateItem(),
|
||||
title = stringResource(id = R.string.check_for_updates_option),
|
||||
description = stringResource(id = R.string.check_for_updates_option_desc)
|
||||
) {
|
||||
onSettingsEvent(
|
||||
SettingsEvent.OnGeneralChangeCheckForUpdates(
|
||||
enable = !state.value.checkForUpdates!!,
|
||||
activity = activity,
|
||||
notificationsPermissionState = notificationsPermissionState,
|
||||
onChangeCheckForUpdates = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeCheckForUpdates(
|
||||
it
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
|
|
@ -17,27 +15,19 @@ import androidx.compose.material3.TopAppBarDefaults
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.domain.util.Constants
|
||||
import ua.acclorite.book_story.domain.util.OnNavigate
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.components.GoBackButton
|
||||
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
|
||||
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.ReaderSettingsCategory
|
||||
|
||||
@Composable
|
||||
fun ReaderSettingsRoot() {
|
||||
|
|
@ -62,12 +52,6 @@ private fun ReaderSettings(
|
|||
) {
|
||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||
|
||||
val fontFamily = remember(state.value.fontFamily) {
|
||||
Constants.FONTS.find {
|
||||
it.id == state.value.fontFamily
|
||||
} ?: Constants.FONTS[0]
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
|
|
@ -96,177 +80,10 @@ private fun ReaderSettings(
|
|||
.padding(top = paddingValues.calculateTopPadding()),
|
||||
state = scrollState.second
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
item {
|
||||
CategoryTitle(
|
||||
title = stringResource(id = R.string.font_reader_settings),
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
|
||||
item {
|
||||
ChipsWithTitle(
|
||||
title = stringResource(id = R.string.font_family_option),
|
||||
chips = Constants.FONTS
|
||||
.map {
|
||||
ButtonItem(
|
||||
it.id,
|
||||
it.fontName.asString(),
|
||||
MaterialTheme.typography.labelLarge.copy(
|
||||
fontFamily = it.font
|
||||
),
|
||||
it.id == fontFamily.id
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
onMainEvent(MainEvent.OnChangeFontFamily(it.id))
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
ChipsWithTitle(
|
||||
title = stringResource(id = R.string.font_style_option),
|
||||
chips = listOf(
|
||||
ButtonItem(
|
||||
"normal",
|
||||
stringResource(id = R.string.font_style_normal),
|
||||
MaterialTheme.typography.labelLarge.copy(
|
||||
fontFamily = fontFamily.font,
|
||||
fontStyle = FontStyle.Normal
|
||||
),
|
||||
!state.value.isItalic!!
|
||||
),
|
||||
ButtonItem(
|
||||
"italic",
|
||||
stringResource(id = R.string.font_style_italic),
|
||||
MaterialTheme.typography.labelLarge.copy(
|
||||
fontFamily = fontFamily.font,
|
||||
fontStyle = FontStyle.Italic
|
||||
),
|
||||
state.value.isItalic!!
|
||||
),
|
||||
),
|
||||
onClick = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeFontStyle(
|
||||
when (it.id) {
|
||||
"italic" -> true
|
||||
else -> false
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
SliderWithTitle(
|
||||
value = state.value.fontSize!! to "pt",
|
||||
fromValue = 10,
|
||||
toValue = 35,
|
||||
title = stringResource(id = R.string.font_size_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeFontSize(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(22.dp))
|
||||
}
|
||||
item {
|
||||
CategoryTitle(
|
||||
title = stringResource(id = R.string.text_reader_settings),
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
item {
|
||||
SliderWithTitle(
|
||||
value = state.value.sidePadding!! to "pt",
|
||||
fromValue = 1,
|
||||
toValue = 20,
|
||||
title = stringResource(id = R.string.side_padding_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeSidePadding(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
SliderWithTitle(
|
||||
value = state.value.lineHeight!! to "pt",
|
||||
fromValue = 1,
|
||||
toValue = 16,
|
||||
title = stringResource(id = R.string.line_height_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeLineHeight(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
SliderWithTitle(
|
||||
value = state.value.paragraphHeight!! to "pt",
|
||||
fromValue = 0,
|
||||
toValue = 24,
|
||||
title = stringResource(id = R.string.paragraph_height_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeParagraphHeight(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
SwitchWithTitle(
|
||||
selected = state.value.paragraphIndentation!!,
|
||||
title = stringResource(id = R.string.paragraph_indentation_option)
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeParagraphIndentation(!state.value.paragraphIndentation!!)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(22.dp))
|
||||
}
|
||||
item {
|
||||
CategoryTitle(
|
||||
title = stringResource(id = R.string.translator_reader_settings),
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
|
||||
item {
|
||||
SwitchWithTitle(
|
||||
selected = state.value.doubleClickTranslation!!,
|
||||
title = stringResource(id = R.string.translator_double_click_to_translate_option),
|
||||
description = stringResource(id = R.string.translator_double_click_to_translate_option_desc),
|
||||
onClick = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeDoubleClickTranslation(
|
||||
!state.value.doubleClickTranslation!!
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
item { Spacer(modifier = Modifier.height(48.dp)) }
|
||||
ReaderSettingsCategory(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
@file:Suppress("FunctionName")
|
||||
|
||||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.FontSubcategory
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TextSubcategory
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TranslatorSubcategory
|
||||
|
||||
/**
|
||||
* Reader Settings Category.
|
||||
* Contains all Reader settings.
|
||||
*
|
||||
* @param state [MainState] instance.
|
||||
* @param onMainEvent [MainEvent] callback.
|
||||
* @param titleColor Color that [CategoryTitle] has.
|
||||
* @param topPadding Top padding to be applied.
|
||||
* @param bottomPadding Bottom padding to be applied.
|
||||
*/
|
||||
fun LazyListScope.ReaderSettingsCategory(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||
topPadding: Dp = 16.dp,
|
||||
bottomPadding: Dp = 48.dp
|
||||
) {
|
||||
FontSubcategory(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent,
|
||||
titleColor = titleColor,
|
||||
topPadding = topPadding,
|
||||
bottomPadding = 0.dp
|
||||
)
|
||||
TextSubcategory(
|
||||
state,
|
||||
onMainEvent = onMainEvent,
|
||||
titleColor = titleColor,
|
||||
topPadding = 22.dp,
|
||||
bottomPadding = 0.dp
|
||||
)
|
||||
TranslatorSubcategory(
|
||||
state,
|
||||
onMainEvent = onMainEvent,
|
||||
titleColor = titleColor,
|
||||
topPadding = 22.dp,
|
||||
bottomPadding = bottomPadding
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||
|
||||
/**
|
||||
* Double Click Translation setting.
|
||||
* Changes Reader's double click translation.
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.DoubleClickTranslationSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
SwitchWithTitle(
|
||||
selected = state.value.doubleClickTranslation!!,
|
||||
modifier = Modifier.animateItem(),
|
||||
title = stringResource(id = R.string.translator_double_click_to_translate_option),
|
||||
description = stringResource(id = R.string.translator_double_click_to_translate_option_desc),
|
||||
onClick = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeDoubleClickTranslation(
|
||||
!state.value.doubleClickTranslation!!
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.domain.util.Constants
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
|
||||
|
||||
/**
|
||||
* Font Family setting.
|
||||
* Changes Reader's font, uses fonts from [Constants.FONTS].
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.FontFamilySetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
val fontFamily = remember(state.value.fontFamily) {
|
||||
Constants.FONTS.find {
|
||||
it.id == state.value.fontFamily
|
||||
} ?: Constants.FONTS[0]
|
||||
}
|
||||
|
||||
ChipsWithTitle(
|
||||
title = stringResource(id = R.string.font_family_option),
|
||||
modifier = Modifier.animateItem(),
|
||||
chips = Constants.FONTS
|
||||
.map {
|
||||
ButtonItem(
|
||||
it.id,
|
||||
it.fontName.asString(),
|
||||
MaterialTheme.typography.labelLarge.copy(
|
||||
fontFamily = it.font
|
||||
),
|
||||
it.id == fontFamily.id
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
onMainEvent(MainEvent.OnChangeFontFamily(it.id))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||
|
||||
/**
|
||||
* Font Size setting.
|
||||
* Changes Reader's font size.
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.FontSizeSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
SliderWithTitle(
|
||||
value = state.value.fontSize!! to "pt",
|
||||
modifier = Modifier.animateItem(),
|
||||
fromValue = 10,
|
||||
toValue = 35,
|
||||
title = stringResource(id = R.string.font_size_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeFontSize(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.domain.util.Constants
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
|
||||
|
||||
/**
|
||||
* Font Style setting.
|
||||
* Changes Reader's font style (Normal/Italic).
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.FontStyleSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
val fontFamily = remember(state.value.fontFamily) {
|
||||
Constants.FONTS.find {
|
||||
it.id == state.value.fontFamily
|
||||
} ?: Constants.FONTS[0]
|
||||
}
|
||||
|
||||
ChipsWithTitle(
|
||||
title = stringResource(id = R.string.font_style_option),
|
||||
modifier = Modifier.animateItem(),
|
||||
chips = listOf(
|
||||
ButtonItem(
|
||||
"normal",
|
||||
stringResource(id = R.string.font_style_normal),
|
||||
MaterialTheme.typography.labelLarge.copy(
|
||||
fontFamily = fontFamily.font,
|
||||
fontStyle = FontStyle.Normal
|
||||
),
|
||||
!state.value.isItalic!!
|
||||
),
|
||||
ButtonItem(
|
||||
"italic",
|
||||
stringResource(id = R.string.font_style_italic),
|
||||
MaterialTheme.typography.labelLarge.copy(
|
||||
fontFamily = fontFamily.font,
|
||||
fontStyle = FontStyle.Italic
|
||||
),
|
||||
state.value.isItalic!!
|
||||
),
|
||||
),
|
||||
onClick = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeFontStyle(
|
||||
when (it.id) {
|
||||
"italic" -> true
|
||||
else -> false
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||
|
||||
/**
|
||||
* Line Height setting.
|
||||
* Changes Reader's line height.
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.LineHeightSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
SliderWithTitle(
|
||||
value = state.value.lineHeight!! to "pt",
|
||||
modifier = Modifier.animateItem(),
|
||||
fromValue = 1,
|
||||
toValue = 16,
|
||||
title = stringResource(id = R.string.line_height_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeLineHeight(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||
|
||||
/**
|
||||
* Paragraph Height setting.
|
||||
* Changes Reader's paragraph height.
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.ParagraphHeightSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
SliderWithTitle(
|
||||
value = state.value.paragraphHeight!! to "pt",
|
||||
modifier = Modifier.animateItem(),
|
||||
fromValue = 0,
|
||||
toValue = 24,
|
||||
title = stringResource(id = R.string.paragraph_height_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeParagraphHeight(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||
|
||||
/**
|
||||
* Paragraph Indentation setting.
|
||||
* Changes Reader's paragraph indentation.
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.ParagraphIndentationSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
SwitchWithTitle(
|
||||
selected = state.value.paragraphIndentation!!,
|
||||
modifier = Modifier.animateItem(),
|
||||
title = stringResource(id = R.string.paragraph_indentation_option)
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeParagraphIndentation(!state.value.paragraphIndentation!!)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||
|
||||
/**
|
||||
* Side Padding setting.
|
||||
* Changes Reader's side padding.
|
||||
*/
|
||||
@Composable
|
||||
fun LazyItemScope.SidePaddingSetting(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
SliderWithTitle(
|
||||
value = state.value.sidePadding!! to "pt",
|
||||
modifier = Modifier.animateItem(),
|
||||
fromValue = 1,
|
||||
toValue = 20,
|
||||
title = stringResource(id = R.string.side_padding_option),
|
||||
onValueChange = {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeSidePadding(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
@file:Suppress("FunctionName")
|
||||
|
||||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.coerceAtLeast
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.FontFamilySetting
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.FontSizeSetting
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.FontStyleSetting
|
||||
|
||||
/**
|
||||
* Font subcategory.
|
||||
* Contains all settings from Font.
|
||||
*/
|
||||
fun LazyListScope.FontSubcategory(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||
title: @Composable () -> String = { stringResource(id = R.string.font_reader_settings) },
|
||||
showTitle: Boolean = true,
|
||||
topPadding: Dp,
|
||||
bottomPadding: Dp
|
||||
) {
|
||||
item {
|
||||
if (showTitle) {
|
||||
CategoryTitle(
|
||||
title = title.invoke(),
|
||||
color = titleColor.invoke(),
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.padding(
|
||||
top = topPadding,
|
||||
bottom = 8.dp
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height((topPadding - 8.dp).coerceAtLeast(0.dp))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
FontFamilySetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
FontStyleSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
FontSizeSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(bottomPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
@file:Suppress("FunctionName")
|
||||
|
||||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.coerceAtLeast
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.LineHeightSetting
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.ParagraphHeightSetting
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.ParagraphIndentationSetting
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.SidePaddingSetting
|
||||
|
||||
/**
|
||||
* Text subcategory.
|
||||
* Contains all settings from Text.
|
||||
*/
|
||||
fun LazyListScope.TextSubcategory(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||
title: @Composable () -> String = { stringResource(id = R.string.text_reader_settings) },
|
||||
showTitle: Boolean = true,
|
||||
topPadding: Dp,
|
||||
bottomPadding: Dp
|
||||
) {
|
||||
item {
|
||||
if (showTitle) {
|
||||
CategoryTitle(
|
||||
title = title.invoke(),
|
||||
color = titleColor.invoke(),
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.padding(
|
||||
top = topPadding,
|
||||
bottom = 8.dp
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height((topPadding - 8.dp).coerceAtLeast(0.dp))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
SidePaddingSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
LineHeightSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
ParagraphHeightSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
ParagraphIndentationSetting(
|
||||
state = state,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(bottomPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
@file:Suppress("FunctionName")
|
||||
|
||||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.coerceAtLeast
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.DoubleClickTranslationSetting
|
||||
|
||||
/**
|
||||
* Translator subcategory.
|
||||
* Contains all settings from Translator.
|
||||
*/
|
||||
fun LazyListScope.TranslatorSubcategory(
|
||||
state: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||
title: @Composable () -> String = { stringResource(id = R.string.translator_reader_settings) },
|
||||
showTitle: Boolean = true,
|
||||
topPadding: Dp,
|
||||
bottomPadding: Dp
|
||||
) {
|
||||
item {
|
||||
if (showTitle) {
|
||||
CategoryTitle(
|
||||
title = title.invoke(),
|
||||
color = titleColor.invoke(),
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.padding(
|
||||
top = topPadding,
|
||||
bottom = 8.dp
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height((topPadding - 8.dp).coerceAtLeast(0.dp))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
DoubleClickTranslationSetting(
|
||||
state = state,
|
||||
onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(bottomPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,172 +1,26 @@
|
|||
package ua.acclorite.book_story.presentation.screens.start.components
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.domain.model.ButtonItem
|
||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||
import ua.acclorite.book_story.presentation.data.MainState
|
||||
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.theme_switcher.AppearanceSettingsThemeSwitcher
|
||||
import ua.acclorite.book_story.presentation.ui.BookStoryTheme
|
||||
import ua.acclorite.book_story.presentation.ui.DarkTheme
|
||||
import ua.acclorite.book_story.presentation.ui.PureDark
|
||||
import ua.acclorite.book_story.presentation.ui.SlidingTransition
|
||||
import ua.acclorite.book_story.presentation.ui.Theme
|
||||
import ua.acclorite.book_story.presentation.ui.ThemeContrast
|
||||
import ua.acclorite.book_story.presentation.ui.isDark
|
||||
import ua.acclorite.book_story.presentation.ui.isPureDark
|
||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ThemePreferencesSubcategory
|
||||
|
||||
/**
|
||||
* Appearance settings.
|
||||
*/
|
||||
fun LazyListScope.startAppearanceScreen(
|
||||
mainState: State<MainState>,
|
||||
onMainEvent: (MainEvent) -> Unit,
|
||||
themeContrastTheme: State<Theme>
|
||||
onMainEvent: (MainEvent) -> Unit
|
||||
) {
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(16.dp)
|
||||
)
|
||||
}
|
||||
item {
|
||||
CategoryTitle(
|
||||
modifier = Modifier.animateItem(),
|
||||
title = stringResource(id = R.string.start_theme_preferences),
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
SegmentedButtonWithTitle(
|
||||
modifier = Modifier.animateItem(),
|
||||
title = stringResource(id = R.string.dark_theme_option),
|
||||
locked = true,
|
||||
buttons = DarkTheme.entries.map {
|
||||
ButtonItem(
|
||||
it.toString(),
|
||||
when (it) {
|
||||
DarkTheme.OFF -> stringResource(id = R.string.dark_theme_off)
|
||||
DarkTheme.ON -> stringResource(id = R.string.dark_theme_on)
|
||||
DarkTheme.FOLLOW_SYSTEM -> stringResource(id = R.string.dark_theme_follow_system)
|
||||
},
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it == mainState.value.darkTheme
|
||||
)
|
||||
}
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeDarkTheme(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
AppearanceSettingsThemeSwitcher(
|
||||
modifier = Modifier.animateItem(),
|
||||
state = mainState,
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BookStoryTheme(
|
||||
theme = themeContrastTheme.value,
|
||||
isDark = mainState.value.darkTheme!!.isDark(),
|
||||
isPureDark = mainState.value.pureDark!!.isPureDark(context = LocalContext.current),
|
||||
themeContrast = mainState.value.themeContrast!!
|
||||
) {
|
||||
SlidingTransition(
|
||||
modifier = Modifier.animateItem(
|
||||
fadeInSpec = null,
|
||||
fadeOutSpec = null
|
||||
),
|
||||
visible = mainState.value.theme != Theme.DYNAMIC,
|
||||
) {
|
||||
SegmentedButtonWithTitle(
|
||||
title = stringResource(id = R.string.theme_contrast_option),
|
||||
locked = mainState.value.theme != Theme.DYNAMIC,
|
||||
buttons = ThemeContrast.entries.map {
|
||||
ButtonItem(
|
||||
it.toString(),
|
||||
when (it) {
|
||||
ThemeContrast.STANDARD -> stringResource(id = R.string.theme_contrast_standard)
|
||||
ThemeContrast.MEDIUM -> stringResource(id = R.string.theme_contrast_medium)
|
||||
ThemeContrast.HIGH -> stringResource(id = R.string.theme_contrast_high)
|
||||
},
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it == mainState.value.themeContrast
|
||||
)
|
||||
}
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangeThemeContrast(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
SlidingTransition(
|
||||
modifier = Modifier.animateItem(
|
||||
fadeInSpec = null,
|
||||
fadeOutSpec = null
|
||||
),
|
||||
visible = mainState.value.darkTheme!!.isDark(),
|
||||
) {
|
||||
SegmentedButtonWithTitle(
|
||||
title = stringResource(id = R.string.pure_dark_option),
|
||||
locked = true,
|
||||
buttons = PureDark.entries.map {
|
||||
ButtonItem(
|
||||
it.toString(),
|
||||
when (it) {
|
||||
PureDark.OFF -> stringResource(id = R.string.pure_dark_off)
|
||||
PureDark.ON -> stringResource(id = R.string.pure_dark_on)
|
||||
PureDark.SAVER -> stringResource(id = R.string.pure_dark_power_saver)
|
||||
},
|
||||
MaterialTheme.typography.labelLarge,
|
||||
it == mainState.value.pureDark
|
||||
)
|
||||
}
|
||||
) {
|
||||
onMainEvent(
|
||||
MainEvent.OnChangePureDark(
|
||||
it.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.height(8.dp)
|
||||
)
|
||||
}
|
||||
ThemePreferencesSubcategory(
|
||||
state = mainState,
|
||||
onMainEvent = onMainEvent,
|
||||
title = { stringResource(id = R.string.start_theme_preferences) },
|
||||
topPadding = 16.dp,
|
||||
bottomPadding = 8.dp
|
||||
)
|
||||
}
|
||||
|
|
@ -19,9 +19,7 @@ import androidx.compose.material3.Icon
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
|
|
@ -40,7 +38,6 @@ import ua.acclorite.book_story.presentation.screens.start.components.permissions
|
|||
import ua.acclorite.book_story.presentation.screens.start.data.StartEvent
|
||||
import ua.acclorite.book_story.presentation.screens.start.data.StartNavigationScreen
|
||||
import ua.acclorite.book_story.presentation.screens.start.data.StartState
|
||||
import ua.acclorite.book_story.presentation.ui.Theme
|
||||
|
||||
/**
|
||||
* Start Settings.
|
||||
|
|
@ -74,13 +71,6 @@ fun StartSettings(
|
|||
)
|
||||
}.sortedBy { it.title }
|
||||
}
|
||||
val themeContrastTheme = remember { mutableStateOf(mainState.value.theme!!) }
|
||||
|
||||
LaunchedEffect(mainState.value.theme) {
|
||||
if (themeContrastTheme.value != mainState.value.theme && mainState.value.theme != Theme.DYNAMIC) {
|
||||
themeContrastTheme.value = mainState.value.theme!!
|
||||
}
|
||||
}
|
||||
|
||||
StartNavigationTransition(
|
||||
modifier = Modifier.padding(horizontal = 18.dp),
|
||||
|
|
@ -148,8 +138,7 @@ fun StartSettings(
|
|||
) {
|
||||
startAppearanceScreen(
|
||||
mainState = mainState,
|
||||
onMainEvent = onMainEvent,
|
||||
themeContrastTheme = themeContrastTheme
|
||||
onMainEvent = onMainEvent
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue