🚀 Highlight words option
* Highlights the beginning of each word * May help some people read faster|understand more * Thickness option to change highlighting strength Resolves: #109
This commit is contained in:
parent
50a645fb32
commit
6500c08512
18 changed files with 373 additions and 57 deletions
|
|
@ -1,7 +1,14 @@
|
|||
package ua.acclorite.book_story.domain.reader
|
||||
|
||||
enum class ReaderTextAlignment {
|
||||
START, JUSTIFY, CENTER, END
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
|
||||
@Immutable
|
||||
enum class ReaderTextAlignment(val textAlignment: TextAlign) {
|
||||
START(TextAlign.Start),
|
||||
JUSTIFY(TextAlign.Justify),
|
||||
CENTER(TextAlign.Center),
|
||||
END(TextAlign.End)
|
||||
}
|
||||
|
||||
fun String.toTextAlignment(): ReaderTextAlignment {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
package ua.acclorite.book_story.presentation.core.components.common
|
||||
|
||||
import androidx.compose.foundation.text.BasicText
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Composable
|
||||
fun HighlightedText(
|
||||
modifier: Modifier = Modifier,
|
||||
text: AnnotatedString,
|
||||
highlightThickness: FontWeight,
|
||||
style: TextStyle
|
||||
) {
|
||||
val highlightedText = remember(text, highlightThickness) {
|
||||
buildAnnotatedString {
|
||||
text.splitAnnotatedString().forEach { word ->
|
||||
if (word.text.none { it.isLetter() }) {
|
||||
append(word)
|
||||
append(" ")
|
||||
return@forEach
|
||||
}
|
||||
|
||||
val textWord = word.text.filterDigitsAtStartAndEnd()
|
||||
val digitsAtStart = word.text.digitsAtStart()
|
||||
val focusArea = when (textWord.length) {
|
||||
in 1..3 -> 1
|
||||
4 -> 2
|
||||
else -> (textWord.length * 0.5f).roundToInt()
|
||||
} + digitsAtStart
|
||||
|
||||
if (digitsAtStart > 0) {
|
||||
append(word.subSequence(0, digitsAtStart))
|
||||
}
|
||||
|
||||
withStyle(style = SpanStyle(fontWeight = highlightThickness)) {
|
||||
append(word.subSequence(digitsAtStart, focusArea))
|
||||
}
|
||||
|
||||
append(word.subSequence(focusArea, word.text.length))
|
||||
append(" ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BasicText(
|
||||
text = highlightedText,
|
||||
modifier = modifier,
|
||||
style = style,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
|
||||
private fun String.digitsAtStart(): Int {
|
||||
var count = 0
|
||||
for (char in this) {
|
||||
if (!char.isLetter()) count++
|
||||
else break
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
private fun String.filterDigitsAtStartAndEnd(): String {
|
||||
return dropWhile { !it.isLetter() }.dropLastWhile { !it.isLetter() }
|
||||
}
|
||||
|
||||
private fun AnnotatedString.splitAnnotatedString(): List<AnnotatedString> {
|
||||
val result = mutableListOf<AnnotatedString>()
|
||||
|
||||
val wordRegex = Regex("\\S+")
|
||||
wordRegex.findAll(this).forEach { matchResult ->
|
||||
val wordStart = matchResult.range.first
|
||||
val wordEnd = matchResult.range.last + 1
|
||||
|
||||
val word = subSequence(wordStart, wordEnd)
|
||||
result.add(word)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
|
@ -45,6 +45,8 @@ object DataStoreConstants {
|
|||
val HORIZONTAL_GESTURE_SCROLL = doublePreferencesKey("horizontal_gesture_scroll")
|
||||
val HORIZONTAL_GESTURE_SENSITIVITY = doublePreferencesKey("horizontal_gesture_sensitivity")
|
||||
val BOTTOM_BAR_PADDING = intPreferencesKey("bottom_bar_padding")
|
||||
val HIGHLIGHTED_READING = booleanPreferencesKey("highlighted_reading")
|
||||
val HIGHLIGHTED_READING_THICKNESS = intPreferencesKey("highlighted_reading_thickness")
|
||||
|
||||
// Browse settings
|
||||
val BROWSE_FILES_STRUCTURE = stringPreferencesKey("browse_files_structure")
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ import androidx.compose.foundation.layout.PaddingValues
|
|||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import ua.acclorite.book_story.domain.library.book.Book
|
||||
|
|
@ -46,6 +48,8 @@ fun ReaderContent(
|
|||
horizontalGesture: ReaderHorizontalGesture,
|
||||
horizontalGestureScroll: Float,
|
||||
horizontalGestureSensitivity: Dp,
|
||||
highlightedReading: Boolean,
|
||||
highlightedReadingThickness: FontWeight,
|
||||
paragraphHeight: Dp,
|
||||
sidePadding: Dp,
|
||||
bottomBarPadding: Dp,
|
||||
|
|
@ -55,6 +59,7 @@ fun ReaderContent(
|
|||
lineHeight: TextUnit,
|
||||
fontStyle: FontStyle,
|
||||
textAlignment: ReaderTextAlignment,
|
||||
horizontalAlignment: Alignment.Horizontal,
|
||||
fontSize: TextUnit,
|
||||
letterSpacing: TextUnit,
|
||||
paragraphIndentation: TextUnit,
|
||||
|
|
@ -107,6 +112,8 @@ fun ReaderContent(
|
|||
horizontalGesture = horizontalGesture,
|
||||
horizontalGestureScroll = horizontalGestureScroll,
|
||||
horizontalGestureSensitivity = horizontalGestureSensitivity,
|
||||
highlightedReading = highlightedReading,
|
||||
highlightedReadingThickness = highlightedReadingThickness,
|
||||
paragraphHeight = paragraphHeight,
|
||||
sidePadding = sidePadding,
|
||||
bottomBarPadding = bottomBarPadding,
|
||||
|
|
@ -116,6 +123,7 @@ fun ReaderContent(
|
|||
lineHeight = lineHeight,
|
||||
fontStyle = fontStyle,
|
||||
textAlignment = textAlignment,
|
||||
horizontalAlignment = horizontalAlignment,
|
||||
fontSize = fontSize,
|
||||
letterSpacing = letterSpacing,
|
||||
paragraphIndentation = paragraphIndentation,
|
||||
|
|
|
|||
|
|
@ -12,9 +12,11 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.compose.ui.unit.coerceAtLeast
|
||||
|
|
@ -40,6 +42,8 @@ fun ReaderLayout(
|
|||
horizontalGesture: ReaderHorizontalGesture,
|
||||
horizontalGestureScroll: Float,
|
||||
horizontalGestureSensitivity: Dp,
|
||||
highlightedReading: Boolean,
|
||||
highlightedReadingThickness: FontWeight,
|
||||
paragraphHeight: Dp,
|
||||
sidePadding: Dp,
|
||||
backgroundColor: Color,
|
||||
|
|
@ -48,6 +52,7 @@ fun ReaderLayout(
|
|||
lineHeight: TextUnit,
|
||||
fontStyle: FontStyle,
|
||||
textAlignment: ReaderTextAlignment,
|
||||
horizontalAlignment: Alignment.Horizontal,
|
||||
fontSize: TextUnit,
|
||||
letterSpacing: TextUnit,
|
||||
paragraphIndentation: TextUnit,
|
||||
|
|
@ -156,12 +161,15 @@ fun ReaderLayout(
|
|||
lineHeight = lineHeight,
|
||||
fontStyle = fontStyle,
|
||||
textAlignment = textAlignment,
|
||||
horizontalAlignment = horizontalAlignment,
|
||||
fontSize = fontSize,
|
||||
letterSpacing = letterSpacing,
|
||||
sidePadding = sidePadding,
|
||||
paragraphIndentation = paragraphIndentation,
|
||||
fullscreenMode = fullscreenMode,
|
||||
doubleClickTranslation = doubleClickTranslation,
|
||||
highlightedReading = highlightedReading,
|
||||
highlightedReadingThickness = highlightedReadingThickness,
|
||||
toolbarHidden = toolbarHidden,
|
||||
openTranslator = openTranslator,
|
||||
menuVisibility = menuVisibility
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ package ua.acclorite.book_story.presentation.reader
|
|||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import ua.acclorite.book_story.domain.reader.FontWithName
|
||||
|
|
@ -22,12 +24,15 @@ fun LazyItemScope.ReaderLayoutText(
|
|||
lineHeight: TextUnit,
|
||||
fontStyle: FontStyle,
|
||||
textAlignment: ReaderTextAlignment,
|
||||
horizontalAlignment: Alignment.Horizontal,
|
||||
fontSize: TextUnit,
|
||||
letterSpacing: TextUnit,
|
||||
sidePadding: Dp,
|
||||
paragraphIndentation: TextUnit,
|
||||
fullscreenMode: Boolean,
|
||||
doubleClickTranslation: Boolean,
|
||||
highlightedReading: Boolean,
|
||||
highlightedReadingThickness: FontWeight,
|
||||
toolbarHidden: Boolean,
|
||||
openTranslator: (ReaderEvent.OnOpenTranslator) -> Unit,
|
||||
menuVisibility: (ReaderEvent.OnMenuVisibility) -> Unit
|
||||
|
|
@ -44,7 +49,9 @@ fun LazyItemScope.ReaderLayoutText(
|
|||
ReaderLayoutTextChapter(
|
||||
chapter = textEntry,
|
||||
fontColor = fontColor,
|
||||
sidePadding = sidePadding
|
||||
sidePadding = sidePadding,
|
||||
highlightedReading = highlightedReading,
|
||||
highlightedReadingThickness = highlightedReadingThickness
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -58,12 +65,15 @@ fun LazyItemScope.ReaderLayoutText(
|
|||
lineHeight = lineHeight,
|
||||
fontStyle = fontStyle,
|
||||
textAlignment = textAlignment,
|
||||
horizontalAlignment = horizontalAlignment,
|
||||
fontSize = fontSize,
|
||||
letterSpacing = letterSpacing,
|
||||
sidePadding = sidePadding,
|
||||
paragraphIndentation = paragraphIndentation,
|
||||
fullscreenMode = fullscreenMode,
|
||||
doubleClickTranslation = doubleClickTranslation,
|
||||
highlightedReading = highlightedReading,
|
||||
highlightedReadingThickness = highlightedReadingThickness,
|
||||
toolbarHidden = toolbarHidden,
|
||||
openTranslator = openTranslator,
|
||||
menuVisibility = menuVisibility
|
||||
|
|
|
|||
|
|
@ -7,25 +7,45 @@ import androidx.compose.material3.HorizontalDivider
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ua.acclorite.book_story.domain.reader.ReaderText.Chapter
|
||||
import ua.acclorite.book_story.presentation.core.components.common.HighlightedText
|
||||
|
||||
@Composable
|
||||
fun ReaderLayoutTextChapter(
|
||||
chapter: Chapter,
|
||||
fontColor: Color,
|
||||
sidePadding: Dp
|
||||
sidePadding: Dp,
|
||||
highlightedReading: Boolean,
|
||||
highlightedReadingThickness: FontWeight
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(22.dp))
|
||||
if (highlightedReading) {
|
||||
HighlightedText(
|
||||
text = rememberSaveable(saver = AnnotatedString.Saver) {
|
||||
buildAnnotatedString { append(chapter.title) }
|
||||
},
|
||||
highlightThickness = highlightedReadingThickness,
|
||||
style = MaterialTheme.typography.headlineMedium.copy(
|
||||
color = fontColor
|
||||
),
|
||||
modifier = Modifier.padding(horizontal = sidePadding)
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
text = chapter.title,
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
color = fontColor,
|
||||
modifier = Modifier.padding(horizontal = sidePadding)
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
HorizontalDivider(color = fontColor.copy(0.4f))
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
|
|
|||
|
|
@ -13,14 +13,16 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontSynthesis
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.LineBreak
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextIndent
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import ua.acclorite.book_story.domain.reader.FontWithName
|
||||
import ua.acclorite.book_story.domain.reader.ReaderText.Text
|
||||
import ua.acclorite.book_story.domain.reader.ReaderTextAlignment
|
||||
import ua.acclorite.book_story.presentation.core.components.common.HighlightedText
|
||||
import ua.acclorite.book_story.presentation.core.util.noRippleClickable
|
||||
import ua.acclorite.book_story.ui.reader.ReaderEvent
|
||||
|
||||
|
|
@ -34,12 +36,15 @@ fun LazyItemScope.ReaderLayoutTextParagraph(
|
|||
lineHeight: TextUnit,
|
||||
fontStyle: FontStyle,
|
||||
textAlignment: ReaderTextAlignment,
|
||||
horizontalAlignment: Alignment.Horizontal,
|
||||
fontSize: TextUnit,
|
||||
letterSpacing: TextUnit,
|
||||
sidePadding: Dp,
|
||||
paragraphIndentation: TextUnit,
|
||||
fullscreenMode: Boolean,
|
||||
doubleClickTranslation: Boolean,
|
||||
highlightedReading: Boolean,
|
||||
highlightedReadingThickness: FontWeight,
|
||||
toolbarHidden: Boolean,
|
||||
openTranslator: (ReaderEvent.OnOpenTranslator) -> Unit,
|
||||
menuVisibility: (ReaderEvent.OnMenuVisibility) -> Unit
|
||||
|
|
@ -50,12 +55,51 @@ fun LazyItemScope.ReaderLayoutTextParagraph(
|
|||
.fillMaxWidth()
|
||||
.padding(horizontal = sidePadding),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = when (textAlignment) {
|
||||
ReaderTextAlignment.START, ReaderTextAlignment.JUSTIFY -> Alignment.Start
|
||||
ReaderTextAlignment.CENTER -> Alignment.CenterHorizontally
|
||||
ReaderTextAlignment.END -> Alignment.End
|
||||
}
|
||||
horizontalAlignment = horizontalAlignment
|
||||
) {
|
||||
if (highlightedReading) {
|
||||
HighlightedText(
|
||||
text = paragraph.line,
|
||||
highlightThickness = highlightedReadingThickness,
|
||||
modifier = Modifier.then(
|
||||
if (doubleClickTranslation && toolbarHidden) {
|
||||
Modifier.noRippleClickable(
|
||||
onDoubleClick = {
|
||||
openTranslator(
|
||||
ReaderEvent.OnOpenTranslator(
|
||||
textToTranslate = paragraph.line.text,
|
||||
translateWholeParagraph = true,
|
||||
activity = activity
|
||||
)
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
menuVisibility(
|
||||
ReaderEvent.OnMenuVisibility(
|
||||
show = !showMenu,
|
||||
fullscreenMode = fullscreenMode,
|
||||
saveCheckpoint = true,
|
||||
activity = activity
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
} else Modifier
|
||||
),
|
||||
style = TextStyle(
|
||||
fontFamily = fontFamily.font,
|
||||
fontSynthesis = FontSynthesis.All,
|
||||
textAlign = textAlignment.textAlignment,
|
||||
textIndent = TextIndent(firstLine = paragraphIndentation),
|
||||
fontStyle = fontStyle,
|
||||
letterSpacing = letterSpacing,
|
||||
fontSize = fontSize,
|
||||
lineHeight = lineHeight,
|
||||
color = fontColor,
|
||||
lineBreak = LineBreak.Paragraph
|
||||
)
|
||||
)
|
||||
} else {
|
||||
BasicText(
|
||||
text = paragraph.line,
|
||||
modifier = Modifier.then(
|
||||
|
|
@ -85,12 +129,7 @@ fun LazyItemScope.ReaderLayoutTextParagraph(
|
|||
),
|
||||
style = TextStyle(
|
||||
fontFamily = fontFamily.font,
|
||||
textAlign = when (textAlignment) {
|
||||
ReaderTextAlignment.START -> TextAlign.Start
|
||||
ReaderTextAlignment.JUSTIFY -> TextAlign.Justify
|
||||
ReaderTextAlignment.CENTER -> TextAlign.Center
|
||||
ReaderTextAlignment.END -> TextAlign.End
|
||||
},
|
||||
textAlign = textAlignment.textAlignment,
|
||||
textIndent = TextIndent(firstLine = paragraphIndentation),
|
||||
fontStyle = fontStyle,
|
||||
letterSpacing = letterSpacing,
|
||||
|
|
@ -101,4 +140,5 @@ fun LazyItemScope.ReaderLayoutTextParagraph(
|
|||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,11 +10,13 @@ import androidx.compose.foundation.lazy.LazyListState
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import ua.acclorite.book_story.domain.library.book.Book
|
||||
|
|
@ -52,6 +54,8 @@ fun ReaderScaffold(
|
|||
horizontalGesture: ReaderHorizontalGesture,
|
||||
horizontalGestureScroll: Float,
|
||||
horizontalGestureSensitivity: Dp,
|
||||
highlightedReading: Boolean,
|
||||
highlightedReadingThickness: FontWeight,
|
||||
paragraphHeight: Dp,
|
||||
sidePadding: Dp,
|
||||
bottomBarPadding: Dp,
|
||||
|
|
@ -61,6 +65,7 @@ fun ReaderScaffold(
|
|||
lineHeight: TextUnit,
|
||||
fontStyle: FontStyle,
|
||||
textAlignment: ReaderTextAlignment,
|
||||
horizontalAlignment: Alignment.Horizontal,
|
||||
fontSize: TextUnit,
|
||||
letterSpacing: TextUnit,
|
||||
paragraphIndentation: TextUnit,
|
||||
|
|
@ -141,6 +146,8 @@ fun ReaderScaffold(
|
|||
horizontalGesture = horizontalGesture,
|
||||
horizontalGestureScroll = horizontalGestureScroll,
|
||||
horizontalGestureSensitivity = horizontalGestureSensitivity,
|
||||
highlightedReading = highlightedReading,
|
||||
highlightedReadingThickness = highlightedReadingThickness,
|
||||
paragraphHeight = paragraphHeight,
|
||||
sidePadding = sidePadding,
|
||||
backgroundColor = backgroundColor,
|
||||
|
|
@ -149,6 +156,7 @@ fun ReaderScaffold(
|
|||
lineHeight = lineHeight,
|
||||
fontStyle = fontStyle,
|
||||
textAlignment = textAlignment,
|
||||
horizontalAlignment = horizontalAlignment,
|
||||
fontSize = fontSize,
|
||||
letterSpacing = letterSpacing,
|
||||
paragraphIndentation = paragraphIndentation,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.settings.components.SettingsSubcategory
|
||||
import ua.acclorite.book_story.presentation.settings.reader.reading_speed.components.HighlightedReadingOption
|
||||
import ua.acclorite.book_story.presentation.settings.reader.reading_speed.components.HighlightedReadingThicknessOption
|
||||
import ua.acclorite.book_story.presentation.settings.reader.reading_speed.components.PerceptionExpanderOption
|
||||
import ua.acclorite.book_story.presentation.settings.reader.reading_speed.components.PerceptionExpanderPaddingOption
|
||||
import ua.acclorite.book_story.presentation.settings.reader.reading_speed.components.PerceptionExpanderThicknessOption
|
||||
|
|
@ -25,6 +27,14 @@ fun LazyListScope.ReadingSpeedSubcategory(
|
|||
showTitle = showTitle,
|
||||
showDivider = showDivider
|
||||
) {
|
||||
item {
|
||||
HighlightedReadingOption()
|
||||
}
|
||||
|
||||
item {
|
||||
HighlightedReadingThicknessOption()
|
||||
}
|
||||
|
||||
item {
|
||||
PerceptionExpanderOption()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package ua.acclorite.book_story.presentation.settings.reader.reading_speed.components
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.core.components.settings.SwitchWithTitle
|
||||
import ua.acclorite.book_story.ui.main.MainEvent
|
||||
import ua.acclorite.book_story.ui.main.MainModel
|
||||
|
||||
@Composable
|
||||
fun HighlightedReadingOption() {
|
||||
val mainModel = hiltViewModel<MainModel>()
|
||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
SwitchWithTitle(
|
||||
selected = state.value.highlightedReading,
|
||||
title = stringResource(id = R.string.highlighted_reading_option),
|
||||
description = stringResource(id = R.string.highlighted_reading_option_desc),
|
||||
onClick = {
|
||||
mainModel.onEvent(
|
||||
MainEvent.OnChangeHighlightedReading(
|
||||
!state.value.highlightedReading
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package ua.acclorite.book_story.presentation.settings.reader.reading_speed.components
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.presentation.core.components.settings.SliderWithTitle
|
||||
import ua.acclorite.book_story.ui.main.MainEvent
|
||||
import ua.acclorite.book_story.ui.main.MainModel
|
||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||
|
||||
@Composable
|
||||
fun HighlightedReadingThicknessOption() {
|
||||
val mainModel = hiltViewModel<MainModel>()
|
||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
ExpandingTransition(visible = state.value.highlightedReading) {
|
||||
SliderWithTitle(
|
||||
value = state.value.highlightedReadingThickness to "pt",
|
||||
fromValue = 1,
|
||||
toValue = 5,
|
||||
title = stringResource(id = R.string.highlighted_reading_thickness_option),
|
||||
onValueChange = {
|
||||
mainModel.onEvent(
|
||||
MainEvent.OnChangeHighlightedReadingThickness(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -47,4 +47,6 @@ sealed class MainEvent {
|
|||
data class OnChangeHorizontalGestureScroll(val value: Float) : MainEvent()
|
||||
data class OnChangeHorizontalGestureSensitivity(val value: Float) : MainEvent()
|
||||
data class OnChangeBottomBarPadding(val value: Int) : MainEvent()
|
||||
data class OnChangeHighlightedReading(val value: Boolean) : MainEvent()
|
||||
data class OnChangeHighlightedReadingThickness(val value: Int) : MainEvent()
|
||||
}
|
||||
|
|
@ -398,6 +398,22 @@ class MainModel @Inject constructor(
|
|||
it.copy(bottomBarPadding = this)
|
||||
}
|
||||
)
|
||||
|
||||
is MainEvent.OnChangeHighlightedReading -> handleDatastoreUpdate(
|
||||
key = DataStoreConstants.HIGHLIGHTED_READING,
|
||||
value = event.value,
|
||||
updateState = {
|
||||
it.copy(highlightedReading = this)
|
||||
}
|
||||
)
|
||||
|
||||
is MainEvent.OnChangeHighlightedReadingThickness -> handleDatastoreUpdate(
|
||||
key = DataStoreConstants.HIGHLIGHTED_READING_THICKNESS,
|
||||
value = event.value,
|
||||
updateState = {
|
||||
it.copy(highlightedReadingThickness = this)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ data class MainState(
|
|||
val horizontalGestureScroll: Float = provideDefaultValue { 0.7f },
|
||||
val horizontalGestureSensitivity: Float = provideDefaultValue { 0.6f },
|
||||
val bottomBarPadding: Int = provideDefaultValue { 0 },
|
||||
val highlightedReading: Boolean = provideDefaultValue { false },
|
||||
val highlightedReadingThickness: Int = provideDefaultValue { 3 },
|
||||
|
||||
// Browse Settings
|
||||
val browseFilesStructure: BrowseFilesStructure = provideDefaultValue {
|
||||
|
|
@ -295,6 +297,14 @@ data class MainState(
|
|||
bottomBarPadding = provideValue(
|
||||
BOTTOM_BAR_PADDING
|
||||
) { bottomBarPadding },
|
||||
|
||||
highlightedReading = provideValue(
|
||||
HIGHLIGHTED_READING
|
||||
) { highlightedReading },
|
||||
|
||||
highlightedReadingThickness = provideValue(
|
||||
HIGHLIGHTED_READING_THICKNESS
|
||||
) { highlightedReadingThickness },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,14 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.em
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
|
@ -162,6 +164,22 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
|||
val horizontalGestureSensitivity = remember(mainState.value.horizontalGestureSensitivity) {
|
||||
(36f + mainState.value.horizontalGestureSensitivity * (4f - 36f)).dp
|
||||
}
|
||||
val highlightedReadingThickness = remember(mainState.value.highlightedReadingThickness) {
|
||||
when (mainState.value.highlightedReadingThickness) {
|
||||
2 -> FontWeight.W600
|
||||
3 -> FontWeight.W700
|
||||
4 -> FontWeight.W800
|
||||
5 -> FontWeight.W900
|
||||
else -> FontWeight.W500
|
||||
}
|
||||
}
|
||||
val horizontalAlignment = remember(mainState.value.textAlignment) {
|
||||
when (mainState.value.textAlignment) {
|
||||
ReaderTextAlignment.START, ReaderTextAlignment.JUSTIFY -> Alignment.Start
|
||||
ReaderTextAlignment.CENTER -> Alignment.CenterHorizontally
|
||||
ReaderTextAlignment.END -> Alignment.End
|
||||
}
|
||||
}
|
||||
|
||||
val density = LocalDensity.current
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
|
|
@ -309,6 +327,8 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
|||
horizontalGesture = mainState.value.horizontalGesture,
|
||||
horizontalGestureScroll = mainState.value.horizontalGestureScroll,
|
||||
horizontalGestureSensitivity = horizontalGestureSensitivity,
|
||||
highlightedReading = mainState.value.highlightedReading,
|
||||
highlightedReadingThickness = highlightedReadingThickness,
|
||||
paragraphHeight = paragraphHeight,
|
||||
sidePadding = sidePadding,
|
||||
bottomBarPadding = bottomBarPadding,
|
||||
|
|
@ -318,6 +338,7 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
|||
lineHeight = lineHeight,
|
||||
fontStyle = fontStyle,
|
||||
textAlignment = mainState.value.textAlignment,
|
||||
horizontalAlignment = horizontalAlignment,
|
||||
fontSize = mainState.value.fontSize.sp,
|
||||
letterSpacing = letterSpacing,
|
||||
paragraphIndentation = paragraphIndentation,
|
||||
|
|
|
|||
|
|
@ -191,6 +191,9 @@
|
|||
<string name="horizontal_gesture_scroll_option">Частка прокрутки</string>
|
||||
<string name="horizontal_gesture_sensitivity_option">Чутливість</string>
|
||||
<string name="bottom_bar_padding_option">Відступ нижньої панелі</string>
|
||||
<string name="highlighted_reading_option">Підсвічування слів</string>
|
||||
<string name="highlighted_reading_option_desc">Підсвічувати початок кожного слова</string>
|
||||
<string name="highlighted_reading_thickness_option">Товщина підсвічування</string>
|
||||
|
||||
<!-- Browse -->
|
||||
<string name="browse_files_structure_option">Структура файлів</string>
|
||||
|
|
|
|||
|
|
@ -246,6 +246,9 @@
|
|||
<string name="horizontal_gesture_scroll_option">Scroll fraction</string>
|
||||
<string name="horizontal_gesture_sensitivity_option">Sensitivity</string>
|
||||
<string name="bottom_bar_padding_option">Bottom bar margin</string>
|
||||
<string name="highlighted_reading_option">Highlight words</string>
|
||||
<string name="highlighted_reading_option_desc">Highlight the beginning of each word</string>
|
||||
<string name="highlighted_reading_thickness_option">Highlight thickness</string>
|
||||
|
||||
<!-- Browse -->
|
||||
<string name="browse_files_structure_option">Files structure</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue