🚀 Add "Letter Spacing" option in Reader

Added "Letter Spacing" option in Reader, which lets user choose relative distance between letters.
This commit is contained in:
Acclorite 2024-08-25 14:40:00 +03:00
parent 49ed8e7696
commit a39dd84bce
10 changed files with 80 additions and 5 deletions

View file

@ -27,6 +27,7 @@ object DataStoreConstants {
val PARAGRAPH_HEIGHT = intPreferencesKey("paragraph_height") val PARAGRAPH_HEIGHT = intPreferencesKey("paragraph_height")
val PARAGRAPH_INDENTATION = booleanPreferencesKey("paragraph_indentation") val PARAGRAPH_INDENTATION = booleanPreferencesKey("paragraph_indentation")
val TEXT_ALIGNMENT = stringPreferencesKey("text_alignment") val TEXT_ALIGNMENT = stringPreferencesKey("text_alignment")
val LETTER_SPACING = intPreferencesKey("letter_spacing")
// Browse settings // Browse settings
val BROWSE_FILES_STRUCTURE = stringPreferencesKey("browse_files_structure") val BROWSE_FILES_STRUCTURE = stringPreferencesKey("browse_files_structure")

View file

@ -30,4 +30,5 @@ sealed class MainEvent {
data class OnChangeBrowseIncludedFilterItem(val item: String) : MainEvent() data class OnChangeBrowseIncludedFilterItem(val item: String) : MainEvent()
data class OnChangeTextAlignment(val alignment: String) : MainEvent() data class OnChangeTextAlignment(val alignment: String) : MainEvent()
data class OnChangeDoublePressExit(val bool: Boolean) : MainEvent() data class OnChangeDoublePressExit(val bool: Boolean) : MainEvent()
data class OnChangeLetterSpacing(val spacing: Int) : MainEvent()
} }

View file

@ -57,6 +57,7 @@ data class MainState(
val doubleClickTranslation: Boolean? = null, val doubleClickTranslation: Boolean? = null,
val fastColorPresetChange: Boolean? = null, val fastColorPresetChange: Boolean? = null,
val textAlignment: ReaderTextAlignment? = null, val textAlignment: ReaderTextAlignment? = null,
val letterSpacing: Int? = null,
// Browse Settings // Browse Settings
val browseFilesStructure: BrowseFilesStructure? = null, val browseFilesStructure: BrowseFilesStructure? = null,
@ -166,6 +167,9 @@ data class MainState(
val doublePressExit = data[DOUBLE_PRESS_EXIT.name] as? Boolean val doublePressExit = data[DOUBLE_PRESS_EXIT.name] as? Boolean
?: false ?: false
val letterSpacing = data[LETTER_SPACING.name] as? Int
?: 0
return MainState( return MainState(
language = language, language = language,
theme = theme.toTheme(), theme = theme.toTheme(),
@ -192,7 +196,8 @@ data class MainState(
browseSortOrderDescending = browseSortOrderDescending, browseSortOrderDescending = browseSortOrderDescending,
browseIncludedFilterItems = browseIncludedFilterItems, browseIncludedFilterItems = browseIncludedFilterItems,
textAlignment = textAlignment.toTextAlignment(), textAlignment = textAlignment.toTextAlignment(),
doublePressExit = doublePressExit doublePressExit = doublePressExit,
letterSpacing = letterSpacing,
) )
} }
} }

View file

@ -359,6 +359,20 @@ class MainViewModel @Inject constructor(
} }
} }
} }
is MainEvent.OnChangeLetterSpacing -> {
viewModelScope.launch(Dispatchers.IO) {
setDatastore.execute(
DataStoreConstants.LETTER_SPACING,
event.spacing
)
updateStateWithSavedHandle {
it.copy(
letterSpacing = event.spacing
)
}
}
}
} }
} }

View file

@ -46,6 +46,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
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.em
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
@ -209,10 +210,15 @@ private fun ReaderScreen(
settingsState.value.selectedColorPreset.fontColor, settingsState.value.selectedColorPreset.fontColor,
label = "" label = ""
) )
val lineHeight = val lineHeight = remember(
remember(mainState.value.fontSize, mainState.value.lineHeight) { mainState.value.fontSize,
(mainState.value.fontSize!! + mainState.value.lineHeight!!).sp mainState.value.lineHeight
} ) {
(mainState.value.fontSize!! + mainState.value.lineHeight!!).sp
}
val letterSpacing = remember(mainState.value.letterSpacing) {
(mainState.value.letterSpacing!! / 100f).em
}
val sidePadding = remember(mainState.value.sidePadding) { val sidePadding = remember(mainState.value.sidePadding) {
(mainState.value.sidePadding!! * 3).dp (mainState.value.sidePadding!! * 3).dp
} }
@ -407,6 +413,7 @@ private fun ReaderScreen(
fontStyle = fontStyle, fontStyle = fontStyle,
textAlignment = mainState.value.textAlignment!!, textAlignment = mainState.value.textAlignment!!,
fontSize = mainState.value.fontSize!!.sp, fontSize = mainState.value.fontSize!!.sp,
letterSpacing = letterSpacing,
sidePadding = sidePadding, sidePadding = sidePadding,
paragraphIndentation = mainState.value.paragraphIndentation!!, paragraphIndentation = mainState.value.paragraphIndentation!!,
doubleClickTranslationEnabled = mainState.value.doubleClickTranslation!!, doubleClickTranslationEnabled = mainState.value.doubleClickTranslation!!,

View file

@ -38,6 +38,7 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.
* @param fontStyle Line's font style. * @param fontStyle Line's font style.
* @param textAlignment Line's text alignment. * @param textAlignment Line's text alignment.
* @param fontSize Line's font size. * @param fontSize Line's font size.
* @param letterSpacing Letter spacing.
* @param sidePadding Line's side padding. * @param sidePadding Line's side padding.
* @param paragraphIndentation Whether Paragraph Indentation is enabled for this line. * @param paragraphIndentation Whether Paragraph Indentation is enabled for this line.
* @param doubleClickTranslationEnabled Whether Double Click Translation is enabled. * @param doubleClickTranslationEnabled Whether Double Click Translation is enabled.
@ -55,6 +56,7 @@ fun LazyItemScope.ReaderTextParagraph(
fontStyle: FontStyle, fontStyle: FontStyle,
textAlignment: ReaderTextAlignment, textAlignment: ReaderTextAlignment,
fontSize: TextUnit, fontSize: TextUnit,
letterSpacing: TextUnit,
sidePadding: Dp, sidePadding: Dp,
paragraphIndentation: Boolean, paragraphIndentation: Boolean,
doubleClickTranslationEnabled: Boolean, doubleClickTranslationEnabled: Boolean,
@ -126,6 +128,7 @@ fun LazyItemScope.ReaderTextParagraph(
ReaderTextAlignment.END -> TextAlign.End ReaderTextAlignment.END -> TextAlign.End
}, },
fontStyle = fontStyle, fontStyle = fontStyle,
letterSpacing = letterSpacing,
fontSize = fontSize, fontSize = fontSize,
lineHeight = lineHeight, lineHeight = lineHeight,
color = fontColor, color = fontColor,

View file

@ -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
/**
* Letter Spacing setting.
* Changes Reader's letter spacing.
*/
@Composable
fun LazyItemScope.LetterSpacingSetting(
state: State<MainState>,
onMainEvent: (MainEvent) -> Unit
) {
SliderWithTitle(
value = state.value.letterSpacing!! to "pt",
modifier = Modifier.animateItem(),
fromValue = -8,
toValue = 16,
title = stringResource(id = R.string.letter_spacing_option),
onValueChange = {
onMainEvent(
MainEvent.OnChangeLetterSpacing(it)
)
}
)
}

View file

@ -22,6 +22,7 @@ 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.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.FontSizeSetting
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.FontStyleSetting import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.FontStyleSetting
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.LetterSpacingSetting
/** /**
* Font subcategory. * Font subcategory.
@ -78,6 +79,13 @@ fun LazyListScope.FontSubcategory(
) )
} }
item {
LetterSpacingSetting(
state = state,
onMainEvent = onMainEvent
)
}
item { item {
Spacer( Spacer(
modifier = Modifier modifier = Modifier

View file

@ -238,6 +238,7 @@
<string name="fast_color_preset_change_option">Швидка зміна пресета кольорів</string> <string name="fast_color_preset_change_option">Швидка зміна пресета кольорів</string>
<string name="fast_color_preset_change_option_desc">Проведіть вліво або вправо, щоб змінити пресет кольорів</string> <string name="fast_color_preset_change_option_desc">Проведіть вліво або вправо, щоб змінити пресет кольорів</string>
<string name="text_alignment_option">Розташування текста</string> <string name="text_alignment_option">Розташування текста</string>
<string name="letter_spacing_option">Відстань між літерами</string>
<!-- Browse --> <!-- Browse -->
<string name="browse_files_structure_option">Структура файлів</string> <string name="browse_files_structure_option">Структура файлів</string>

View file

@ -257,6 +257,7 @@
<string name="fast_color_preset_change_option">Fast color preset change</string> <string name="fast_color_preset_change_option">Fast color preset change</string>
<string name="fast_color_preset_change_option_desc">Swipe left or right to change color preset</string> <string name="fast_color_preset_change_option_desc">Swipe left or right to change color preset</string>
<string name="text_alignment_option">Text alignment</string> <string name="text_alignment_option">Text alignment</string>
<string name="letter_spacing_option">Letter spacing</string>
<!-- Browse --> <!-- Browse -->
<string name="browse_files_structure_option">Files structure</string> <string name="browse_files_structure_option">Files structure</string>