Skip to content

Commit

Permalink
πŸš€ Highlight words option
Browse files Browse the repository at this point in the history
* Highlights the beginning of each word
* May help some people read faster|understand more
* Thickness option to change highlighting strength

Resolves: #109
  • Loading branch information
Acclorite committed Jan 3, 2025
1 parent 50a645f commit 6500c08
Show file tree
Hide file tree
Showing 18 changed files with 373 additions and 57 deletions.
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -46,6 +48,8 @@ fun ReaderContent(
horizontalGesture: ReaderHorizontalGesture,
horizontalGestureScroll: Float,
horizontalGestureSensitivity: Dp,
highlightedReading: Boolean,
highlightedReadingThickness: FontWeight,
paragraphHeight: Dp,
sidePadding: Dp,
bottomBarPadding: Dp,
Expand All @@ -55,6 +59,7 @@ fun ReaderContent(
lineHeight: TextUnit,
fontStyle: FontStyle,
textAlignment: ReaderTextAlignment,
horizontalAlignment: Alignment.Horizontal,
fontSize: TextUnit,
letterSpacing: TextUnit,
paragraphIndentation: TextUnit,
Expand Down Expand Up @@ -107,6 +112,8 @@ fun ReaderContent(
horizontalGesture = horizontalGesture,
horizontalGestureScroll = horizontalGestureScroll,
horizontalGestureSensitivity = horizontalGestureSensitivity,
highlightedReading = highlightedReading,
highlightedReadingThickness = highlightedReadingThickness,
paragraphHeight = paragraphHeight,
sidePadding = sidePadding,
bottomBarPadding = bottomBarPadding,
Expand All @@ -116,6 +123,7 @@ fun ReaderContent(
lineHeight = lineHeight,
fontStyle = fontStyle,
textAlignment = textAlignment,
horizontalAlignment = horizontalAlignment,
fontSize = fontSize,
letterSpacing = letterSpacing,
paragraphIndentation = paragraphIndentation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -40,6 +42,8 @@ fun ReaderLayout(
horizontalGesture: ReaderHorizontalGesture,
horizontalGestureScroll: Float,
horizontalGestureSensitivity: Dp,
highlightedReading: Boolean,
highlightedReadingThickness: FontWeight,
paragraphHeight: Dp,
sidePadding: Dp,
backgroundColor: Color,
Expand All @@ -48,6 +52,7 @@ fun ReaderLayout(
lineHeight: TextUnit,
fontStyle: FontStyle,
textAlignment: ReaderTextAlignment,
horizontalAlignment: Alignment.Horizontal,
fontSize: TextUnit,
letterSpacing: TextUnit,
paragraphIndentation: TextUnit,
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -44,7 +49,9 @@ fun LazyItemScope.ReaderLayoutText(
ReaderLayoutTextChapter(
chapter = textEntry,
fontColor = fontColor,
sidePadding = sidePadding
sidePadding = sidePadding,
highlightedReading = highlightedReading,
highlightedReadingThickness = highlightedReadingThickness
)
}

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Text(
text = chapter.title,
style = MaterialTheme.typography.headlineMedium,
color = fontColor,
modifier = Modifier.padding(horizontal = sidePadding)
)
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))
Expand Down
Loading

0 comments on commit 6500c08

Please sign in to comment.