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.animateColorAsState
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
|
|
@ -23,21 +21,13 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
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 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.components.CustomBottomSheet
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
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.reader.data.ReaderEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ColorsSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.components.ColorPickerWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.ReaderSettingsCategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings bottom sheet. Has General and Colors categories.
|
* Settings bottom sheet. Has General and Colors categories.
|
||||||
|
|
@ -57,12 +47,6 @@ fun ReaderSettingsBottomSheet(
|
||||||
val currentPage by remember { derivedStateOf { pagerState.currentPage } }
|
val currentPage by remember { derivedStateOf { pagerState.currentPage } }
|
||||||
val context = LocalContext.current
|
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
|
val scrimColor = if (currentPage == 1) Color.Transparent
|
||||||
else BottomSheetDefaults.ScrimColor
|
else BottomSheetDefaults.ScrimColor
|
||||||
|
|
||||||
|
|
@ -109,213 +93,24 @@ fun ReaderSettingsBottomSheet(
|
||||||
HorizontalPager(state = pagerState) { page ->
|
HorizontalPager(state = pagerState) { page ->
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
if (page == 0) {
|
if (page == 0) {
|
||||||
item {
|
ReaderSettingsCategory(
|
||||||
Spacer(modifier = Modifier.height(22.dp))
|
state = mainState,
|
||||||
}
|
onMainEvent = onMainEvent,
|
||||||
item {
|
titleColor = { MaterialTheme.colorScheme.onSurface },
|
||||||
CategoryTitle(
|
topPadding = 16.dp,
|
||||||
title = stringResource(id = R.string.font_reader_settings),
|
bottomPadding = 8.dp + it
|
||||||
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!!
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyColumn {
|
||||||
if (page == 1) {
|
if (page == 1) {
|
||||||
item {
|
ColorsSubcategory(
|
||||||
Spacer(modifier = Modifier.height(14.dp))
|
state = mainState,
|
||||||
}
|
onMainEvent = onMainEvent,
|
||||||
item {
|
showTitle = false,
|
||||||
ColorPickerWithTitle(
|
topPadding = 16.dp,
|
||||||
value = Color(mainState.value.backgroundColor!!.toULong()),
|
bottomPadding = 8.dp + it
|
||||||
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
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ChipsWithTitle(
|
fun ChipsWithTitle(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
title: String,
|
title: String,
|
||||||
chips: List<ButtonItem>,
|
chips: List<ButtonItem>,
|
||||||
horizontalPadding: Dp = 18.dp,
|
horizontalPadding: Dp = 18.dp,
|
||||||
|
|
@ -30,7 +31,7 @@ fun ChipsWithTitle(
|
||||||
onClick: (ButtonItem) -> Unit
|
onClick: (ButtonItem) -> Unit
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = horizontalPadding, vertical = verticalPadding)
|
.padding(horizontal = horizontalPadding, vertical = verticalPadding)
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import androidx.compose.ui.unit.dp
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun SwitchWithTitle(
|
fun SwitchWithTitle(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
selected: Boolean,
|
selected: Boolean,
|
||||||
title: String,
|
title: String,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
|
|
@ -38,7 +39,7 @@ fun SwitchWithTitle(
|
||||||
onClick: () -> Unit
|
onClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = modifier
|
||||||
.clickable { onClick() }
|
.clickable { onClick() }
|
||||||
.padding(horizontal = horizontalPadding, vertical = verticalPadding),
|
.padding(horizontal = horizontalPadding, vertical = verticalPadding),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance
|
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.WindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||||
|
|
@ -15,39 +13,21 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import ua.acclorite.book_story.R
|
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.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.GoBackButton
|
||||||
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
|
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
|
||||||
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
import ua.acclorite.book_story.presentation.data.MainState
|
||||||
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.ColorPickerWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.AppearanceSettingsCategory
|
||||||
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
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppearanceSettingsRoot() {
|
fun AppearanceSettingsRoot() {
|
||||||
|
|
@ -71,13 +51,6 @@ private fun AppearanceSettings(
|
||||||
onMainEvent: (MainEvent) -> Unit
|
onMainEvent: (MainEvent) -> Unit
|
||||||
) {
|
) {
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
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(
|
Scaffold(
|
||||||
Modifier
|
Modifier
|
||||||
|
|
@ -107,189 +80,10 @@ private fun AppearanceSettings(
|
||||||
.padding(top = paddingValues.calculateTopPadding()),
|
.padding(top = paddingValues.calculateTopPadding()),
|
||||||
state = scrollState.second
|
state = scrollState.second
|
||||||
) {
|
) {
|
||||||
item {
|
AppearanceSettingsCategory(
|
||||||
Spacer(
|
state = state,
|
||||||
modifier = Modifier
|
onMainEvent = onMainEvent
|
||||||
.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)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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.core.tween
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
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.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
|
||||||
|
|
@ -17,6 +19,8 @@ import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
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.LazyItemScope
|
||||||
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
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
|
||||||
|
|
@ -25,21 +29,80 @@ 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.State
|
||||||
|
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
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
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 ua.acclorite.book_story.R
|
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.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.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.Theme
|
||||||
import ua.acclorite.book_story.presentation.ui.ThemeContrast
|
import ua.acclorite.book_story.presentation.ui.ThemeContrast
|
||||||
import ua.acclorite.book_story.presentation.ui.animatedColorScheme
|
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 theme Target [Theme].
|
||||||
* @param darkTheme Whether should be shown in Dark 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.
|
* @param onClick OnClick callback.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun AppearanceSettingsThemeSwitcherItem(
|
private fun ThemeSettingItem(
|
||||||
theme: Pair<Theme, UIText>,
|
theme: Pair<Theme, UIText>,
|
||||||
darkTheme: Boolean,
|
darkTheme: Boolean,
|
||||||
isPureDark: 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
|
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.WindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||||
|
|
@ -22,15 +17,9 @@ import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
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.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.domain.util.OnNavigate
|
||||||
import ua.acclorite.book_story.presentation.components.GoBackButton
|
import ua.acclorite.book_story.presentation.components.GoBackButton
|
||||||
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
|
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.MainEvent
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
import ua.acclorite.book_story.presentation.data.MainState
|
||||||
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.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.SettingsEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel
|
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.GeneralSettingsCategory
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun GeneralSettingsRoot() {
|
fun GeneralSettingsRoot() {
|
||||||
|
|
@ -59,8 +47,8 @@ fun GeneralSettingsRoot() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPermissionsApi::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun GeneralSettings(
|
private fun GeneralSettings(
|
||||||
state: State<MainState>,
|
state: State<MainState>,
|
||||||
|
|
@ -69,11 +57,6 @@ private fun GeneralSettings(
|
||||||
onMainEvent: (MainEvent) -> Unit
|
onMainEvent: (MainEvent) -> Unit
|
||||||
) {
|
) {
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
val activity = LocalContext.current as ComponentActivity
|
|
||||||
|
|
||||||
val notificationsPermissionState = rememberPermissionState(
|
|
||||||
permission = Manifest.permission.POST_NOTIFICATIONS
|
|
||||||
)
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
Modifier
|
Modifier
|
||||||
|
|
@ -103,53 +86,11 @@ private fun GeneralSettings(
|
||||||
.padding(top = paddingValues.calculateTopPadding()),
|
.padding(top = paddingValues.calculateTopPadding()),
|
||||||
state = scrollState.second
|
state = scrollState.second
|
||||||
) {
|
) {
|
||||||
item {
|
GeneralSettingsCategory(
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
state = state,
|
||||||
}
|
onMainEvent = onMainEvent,
|
||||||
item {
|
onSettingsEvent = onSettingsEvent
|
||||||
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)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
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.WindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||||
|
|
@ -17,27 +15,19 @@ import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.res.stringResource
|
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 androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import ua.acclorite.book_story.R
|
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.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.GoBackButton
|
||||||
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
|
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
|
||||||
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
import ua.acclorite.book_story.presentation.data.MainState
|
||||||
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.ChipsWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.ReaderSettingsCategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderSettingsRoot() {
|
fun ReaderSettingsRoot() {
|
||||||
|
|
@ -62,12 +52,6 @@ private fun ReaderSettings(
|
||||||
) {
|
) {
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
|
|
||||||
val fontFamily = remember(state.value.fontFamily) {
|
|
||||||
Constants.FONTS.find {
|
|
||||||
it.id == state.value.fontFamily
|
|
||||||
} ?: Constants.FONTS[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
|
@ -96,177 +80,10 @@ private fun ReaderSettings(
|
||||||
.padding(top = paddingValues.calculateTopPadding()),
|
.padding(top = paddingValues.calculateTopPadding()),
|
||||||
state = scrollState.second
|
state = scrollState.second
|
||||||
) {
|
) {
|
||||||
item {
|
ReaderSettingsCategory(
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
state = state,
|
||||||
}
|
onMainEvent = onMainEvent
|
||||||
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)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
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.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.runtime.State
|
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.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.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.MainEvent
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
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.subcategories.ThemePreferencesSubcategory
|
||||||
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
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appearance settings.
|
* Appearance settings.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.startAppearanceScreen(
|
fun LazyListScope.startAppearanceScreen(
|
||||||
mainState: State<MainState>,
|
mainState: State<MainState>,
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
onMainEvent: (MainEvent) -> Unit
|
||||||
themeContrastTheme: State<Theme>
|
|
||||||
) {
|
) {
|
||||||
item {
|
ThemePreferencesSubcategory(
|
||||||
Spacer(
|
state = mainState,
|
||||||
modifier = Modifier
|
onMainEvent = onMainEvent,
|
||||||
.animateItem()
|
title = { stringResource(id = R.string.start_theme_preferences) },
|
||||||
.height(16.dp)
|
topPadding = 16.dp,
|
||||||
)
|
bottomPadding = 8.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)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -19,9 +19,7 @@ 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.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
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.StartEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.start.data.StartNavigationScreen
|
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.screens.start.data.StartState
|
||||||
import ua.acclorite.book_story.presentation.ui.Theme
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start Settings.
|
* Start Settings.
|
||||||
|
|
@ -74,13 +71,6 @@ fun StartSettings(
|
||||||
)
|
)
|
||||||
}.sortedBy { it.title }
|
}.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(
|
StartNavigationTransition(
|
||||||
modifier = Modifier.padding(horizontal = 18.dp),
|
modifier = Modifier.padding(horizontal = 18.dp),
|
||||||
|
|
@ -148,8 +138,7 @@ fun StartSettings(
|
||||||
) {
|
) {
|
||||||
startAppearanceScreen(
|
startAppearanceScreen(
|
||||||
mainState = mainState,
|
mainState = mainState,
|
||||||
onMainEvent = onMainEvent,
|
onMainEvent = onMainEvent
|
||||||
themeContrastTheme = themeContrastTheme
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue