🚀 Reader horizontal gesture option
* Temporary replacement of Paged Layout * Scrolls by specified amount (scroll fraction) after dragging horizontally * Fade + Offset animation to visualize "dragging" * By default is turned off * Placed in the new Reading Mode subcategory of Reader Settings Resolves: #127
This commit is contained in:
parent
dd3fc17a6f
commit
ba2104ad05
17 changed files with 330 additions and 1 deletions
|
|
@ -0,0 +1,11 @@
|
||||||
|
package ua.acclorite.book_story.domain.reader
|
||||||
|
|
||||||
|
enum class ReaderHorizontalGesture {
|
||||||
|
OFF,
|
||||||
|
ON,
|
||||||
|
INVERSE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.toHorizontalGesture(): ReaderHorizontalGesture {
|
||||||
|
return ReaderHorizontalGesture.valueOf(this)
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,8 @@ object DataStoreConstants {
|
||||||
val SCREEN_ORIENTATION = stringPreferencesKey("screen_orientation")
|
val SCREEN_ORIENTATION = stringPreferencesKey("screen_orientation")
|
||||||
val CUSTOM_SCREEN_BRIGHTNESS = booleanPreferencesKey("custom_screen_brightness")
|
val CUSTOM_SCREEN_BRIGHTNESS = booleanPreferencesKey("custom_screen_brightness")
|
||||||
val SCREEN_BRIGHTNESS = doublePreferencesKey("screen_brightness")
|
val SCREEN_BRIGHTNESS = doublePreferencesKey("screen_brightness")
|
||||||
|
val HORIZONTAL_GESTURE = stringPreferencesKey("horizontal_gesture")
|
||||||
|
val HORIZONTAL_GESTURE_SCROLL = doublePreferencesKey("horizontal_gesture_scroll")
|
||||||
|
|
||||||
// Browse settings
|
// Browse settings
|
||||||
val BROWSE_FILES_STRUCTURE = stringPreferencesKey("browse_files_structure")
|
val BROWSE_FILES_STRUCTURE = stringPreferencesKey("browse_files_structure")
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import ua.acclorite.book_story.domain.library.book.Book
|
||||||
import ua.acclorite.book_story.domain.reader.Chapter
|
import ua.acclorite.book_story.domain.reader.Chapter
|
||||||
import ua.acclorite.book_story.domain.reader.Checkpoint
|
import ua.acclorite.book_story.domain.reader.Checkpoint
|
||||||
import ua.acclorite.book_story.domain.reader.FontWithName
|
import ua.acclorite.book_story.domain.reader.FontWithName
|
||||||
|
import ua.acclorite.book_story.domain.reader.ReaderHorizontalGesture
|
||||||
import ua.acclorite.book_story.domain.reader.ReaderTextAlignment
|
import ua.acclorite.book_story.domain.reader.ReaderTextAlignment
|
||||||
import ua.acclorite.book_story.domain.ui.UIText
|
import ua.acclorite.book_story.domain.ui.UIText
|
||||||
import ua.acclorite.book_story.domain.util.BottomSheet
|
import ua.acclorite.book_story.domain.util.BottomSheet
|
||||||
|
|
@ -46,6 +47,8 @@ fun ReaderContent(
|
||||||
chapters: Map<Int, Chapter>,
|
chapters: Map<Int, Chapter>,
|
||||||
contentPadding: PaddingValues,
|
contentPadding: PaddingValues,
|
||||||
verticalPadding: Dp,
|
verticalPadding: Dp,
|
||||||
|
horizontalGesture: ReaderHorizontalGesture,
|
||||||
|
horizontalGestureScroll: Float,
|
||||||
paragraphHeight: Dp,
|
paragraphHeight: Dp,
|
||||||
sidePadding: Dp,
|
sidePadding: Dp,
|
||||||
backgroundColor: Color,
|
backgroundColor: Color,
|
||||||
|
|
@ -117,6 +120,8 @@ fun ReaderContent(
|
||||||
chapters = chapters,
|
chapters = chapters,
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
verticalPadding = verticalPadding,
|
verticalPadding = verticalPadding,
|
||||||
|
horizontalGesture = horizontalGesture,
|
||||||
|
horizontalGestureScroll = horizontalGestureScroll,
|
||||||
paragraphHeight = paragraphHeight,
|
paragraphHeight = paragraphHeight,
|
||||||
sidePadding = sidePadding,
|
sidePadding = sidePadding,
|
||||||
backgroundColor = backgroundColor,
|
backgroundColor = backgroundColor,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
package ua.acclorite.book_story.presentation.reader
|
||||||
|
|
||||||
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
|
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
|
||||||
|
import androidx.compose.foundation.gestures.scrollBy
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.mutableFloatStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.rememberUpdatedState
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.alpha
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.unit.IntOffset
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import ua.acclorite.book_story.domain.reader.ReaderHorizontalGesture
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Modifier.readerHorizontalGesture(
|
||||||
|
listState: LazyListState,
|
||||||
|
horizontalGesture: ReaderHorizontalGesture,
|
||||||
|
horizontalGestureScroll: Float,
|
||||||
|
isLoading: Boolean
|
||||||
|
): Modifier {
|
||||||
|
if (horizontalGesture == ReaderHorizontalGesture.OFF || isLoading) return this
|
||||||
|
val inverted = rememberUpdatedState(horizontalGesture == ReaderHorizontalGesture.INVERSE)
|
||||||
|
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val density = LocalDensity.current
|
||||||
|
|
||||||
|
val screenHeight = remember {
|
||||||
|
mutableFloatStateOf(0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scrollBackward() {
|
||||||
|
scope.launch {
|
||||||
|
listState.scrollBy(-screenHeight.floatValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scrollForward() {
|
||||||
|
scope.launch {
|
||||||
|
listState.scrollBy(screenHeight.floatValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val horizontalOffset = remember {
|
||||||
|
mutableFloatStateOf(0f)
|
||||||
|
}
|
||||||
|
val animatedHorizontalOffset = animateFloatAsState(
|
||||||
|
horizontalOffset.floatValue
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun calculateAlpha(): Float {
|
||||||
|
return animateFloatAsState(
|
||||||
|
1f - (abs(with(density) { horizontalOffset.floatValue.toDp() }.value) / 16f)
|
||||||
|
).value
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
.onGloballyPositioned {
|
||||||
|
screenHeight.floatValue = it.size.height * horizontalGestureScroll
|
||||||
|
}
|
||||||
|
.alpha(calculateAlpha())
|
||||||
|
.offset {
|
||||||
|
IntOffset(
|
||||||
|
x = animatedHorizontalOffset.value.roundToInt(),
|
||||||
|
y = 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.pointerInput(Unit) {
|
||||||
|
detectHorizontalDragGestures(
|
||||||
|
onDragStart = {
|
||||||
|
horizontalOffset.floatValue = 0f
|
||||||
|
},
|
||||||
|
onHorizontalDrag = { change, dragAmount ->
|
||||||
|
horizontalOffset.floatValue += (dragAmount * 0.15f)
|
||||||
|
},
|
||||||
|
onDragCancel = {
|
||||||
|
horizontalOffset.floatValue = 0f
|
||||||
|
},
|
||||||
|
onDragEnd = {
|
||||||
|
val horizontalOffsetDp = with(density) { horizontalOffset.floatValue.toDp() }
|
||||||
|
|
||||||
|
when {
|
||||||
|
horizontalOffsetDp > 16.dp -> {
|
||||||
|
if (inverted.value) scrollForward()
|
||||||
|
else scrollBackward()
|
||||||
|
}
|
||||||
|
|
||||||
|
horizontalOffsetDp < (-16).dp -> {
|
||||||
|
if (inverted.value) scrollBackward()
|
||||||
|
else scrollForward()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
horizontalOffset.floatValue = 0f
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.domain.reader.Chapter
|
import ua.acclorite.book_story.domain.reader.Chapter
|
||||||
import ua.acclorite.book_story.domain.reader.FontWithName
|
import ua.acclorite.book_story.domain.reader.FontWithName
|
||||||
|
import ua.acclorite.book_story.domain.reader.ReaderHorizontalGesture
|
||||||
import ua.acclorite.book_story.domain.reader.ReaderTextAlignment
|
import ua.acclorite.book_story.domain.reader.ReaderTextAlignment
|
||||||
import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
|
import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
|
||||||
import ua.acclorite.book_story.presentation.core.components.common.SelectionContainer
|
import ua.acclorite.book_story.presentation.core.components.common.SelectionContainer
|
||||||
|
|
@ -38,6 +39,8 @@ fun ReaderLayout(
|
||||||
listState: LazyListState,
|
listState: LazyListState,
|
||||||
contentPadding: PaddingValues,
|
contentPadding: PaddingValues,
|
||||||
verticalPadding: Dp,
|
verticalPadding: Dp,
|
||||||
|
horizontalGesture: ReaderHorizontalGesture,
|
||||||
|
horizontalGestureScroll: Float,
|
||||||
paragraphHeight: Dp,
|
paragraphHeight: Dp,
|
||||||
sidePadding: Dp,
|
sidePadding: Dp,
|
||||||
backgroundColor: Color,
|
backgroundColor: Color,
|
||||||
|
|
@ -124,7 +127,13 @@ fun ReaderLayout(
|
||||||
} else Modifier
|
} else Modifier
|
||||||
)
|
)
|
||||||
.padding(contentPadding)
|
.padding(contentPadding)
|
||||||
.padding(vertical = verticalPadding),
|
.padding(vertical = verticalPadding)
|
||||||
|
.readerHorizontalGesture(
|
||||||
|
listState = listState,
|
||||||
|
horizontalGesture = horizontalGesture,
|
||||||
|
horizontalGestureScroll = horizontalGestureScroll,
|
||||||
|
isLoading = isLoading
|
||||||
|
),
|
||||||
verticalArrangement = Arrangement.spacedBy(paragraphHeight),
|
verticalArrangement = Arrangement.spacedBy(paragraphHeight),
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
top = (WindowInsets.displayCutout.asPaddingValues()
|
top = (WindowInsets.displayCutout.asPaddingValues()
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import ua.acclorite.book_story.domain.library.book.Book
|
||||||
import ua.acclorite.book_story.domain.reader.Chapter
|
import ua.acclorite.book_story.domain.reader.Chapter
|
||||||
import ua.acclorite.book_story.domain.reader.Checkpoint
|
import ua.acclorite.book_story.domain.reader.Checkpoint
|
||||||
import ua.acclorite.book_story.domain.reader.FontWithName
|
import ua.acclorite.book_story.domain.reader.FontWithName
|
||||||
|
import ua.acclorite.book_story.domain.reader.ReaderHorizontalGesture
|
||||||
import ua.acclorite.book_story.domain.reader.ReaderTextAlignment
|
import ua.acclorite.book_story.domain.reader.ReaderTextAlignment
|
||||||
import ua.acclorite.book_story.domain.ui.UIText
|
import ua.acclorite.book_story.domain.ui.UIText
|
||||||
import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
|
import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
|
||||||
|
|
@ -51,6 +52,8 @@ fun ReaderScaffold(
|
||||||
chapters: Map<Int, Chapter>,
|
chapters: Map<Int, Chapter>,
|
||||||
contentPadding: PaddingValues,
|
contentPadding: PaddingValues,
|
||||||
verticalPadding: Dp,
|
verticalPadding: Dp,
|
||||||
|
horizontalGesture: ReaderHorizontalGesture,
|
||||||
|
horizontalGestureScroll: Float,
|
||||||
paragraphHeight: Dp,
|
paragraphHeight: Dp,
|
||||||
sidePadding: Dp,
|
sidePadding: Dp,
|
||||||
backgroundColor: Color,
|
backgroundColor: Color,
|
||||||
|
|
@ -142,6 +145,8 @@ fun ReaderScaffold(
|
||||||
listState = listState,
|
listState = listState,
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
verticalPadding = verticalPadding,
|
verticalPadding = verticalPadding,
|
||||||
|
horizontalGesture = horizontalGesture,
|
||||||
|
horizontalGestureScroll = horizontalGestureScroll,
|
||||||
paragraphHeight = paragraphHeight,
|
paragraphHeight = paragraphHeight,
|
||||||
sidePadding = sidePadding,
|
sidePadding = sidePadding,
|
||||||
backgroundColor = backgroundColor,
|
backgroundColor = backgroundColor,
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import ua.acclorite.book_story.presentation.settings.appearance.colors.ColorsSub
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.font.FontSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.font.FontSubcategory
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.misc.MiscSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.misc.MiscSubcategory
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.padding.PaddingSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.padding.PaddingSubcategory
|
||||||
|
import ua.acclorite.book_story.presentation.settings.reader.reading_mode.ReadingModeSubcategory
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.reading_speed.ReadingSpeedSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.reading_speed.ReadingSpeedSubcategory
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.system.SystemSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.system.SystemSubcategory
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.text.TextSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.text.TextSubcategory
|
||||||
|
|
@ -93,6 +94,11 @@ fun ReaderSettingsBottomSheet(
|
||||||
when (page) {
|
when (page) {
|
||||||
0 -> {
|
0 -> {
|
||||||
LazyColumnWithScrollbar(Modifier.fillMaxSize()) {
|
LazyColumnWithScrollbar(Modifier.fillMaxSize()) {
|
||||||
|
ReadingModeSubcategory(
|
||||||
|
titleColor = { MaterialTheme.colorScheme.onSurface },
|
||||||
|
topPadding = 22.dp,
|
||||||
|
bottomPadding = 0.dp
|
||||||
|
)
|
||||||
PaddingSubcategory(
|
PaddingSubcategory(
|
||||||
titleColor = { MaterialTheme.colorScheme.onSurface },
|
titleColor = { MaterialTheme.colorScheme.onSurface },
|
||||||
topPadding = 22.dp,
|
topPadding = 22.dp,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.font.FontSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.font.FontSubcategory
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.misc.MiscSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.misc.MiscSubcategory
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.padding.PaddingSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.padding.PaddingSubcategory
|
||||||
|
import ua.acclorite.book_story.presentation.settings.reader.reading_mode.ReadingModeSubcategory
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.reading_speed.ReadingSpeedSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.reading_speed.ReadingSpeedSubcategory
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.system.SystemSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.system.SystemSubcategory
|
||||||
import ua.acclorite.book_story.presentation.settings.reader.text.TextSubcategory
|
import ua.acclorite.book_story.presentation.settings.reader.text.TextSubcategory
|
||||||
|
|
@ -31,6 +32,11 @@ fun LazyListScope.ReaderSettingsCategory(
|
||||||
topPadding = 22.dp,
|
topPadding = 22.dp,
|
||||||
bottomPadding = 0.dp
|
bottomPadding = 0.dp
|
||||||
)
|
)
|
||||||
|
ReadingModeSubcategory(
|
||||||
|
titleColor = titleColor,
|
||||||
|
topPadding = 22.dp,
|
||||||
|
bottomPadding = 0.dp
|
||||||
|
)
|
||||||
PaddingSubcategory(
|
PaddingSubcategory(
|
||||||
titleColor = titleColor,
|
titleColor = titleColor,
|
||||||
topPadding = 22.dp,
|
topPadding = 22.dp,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
@file:Suppress("FunctionName")
|
||||||
|
|
||||||
|
package ua.acclorite.book_story.presentation.settings.reader.reading_mode
|
||||||
|
|
||||||
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.settings.components.SettingsSubcategory
|
||||||
|
import ua.acclorite.book_story.presentation.settings.reader.reading_mode.components.HorizontalGestureOption
|
||||||
|
import ua.acclorite.book_story.presentation.settings.reader.reading_mode.components.HorizontalGestureScrollOption
|
||||||
|
|
||||||
|
fun LazyListScope.ReadingModeSubcategory(
|
||||||
|
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||||
|
title: @Composable () -> String = { stringResource(id = R.string.reading_mode_reader_settings) },
|
||||||
|
showTitle: Boolean = true,
|
||||||
|
showDivider: Boolean = true,
|
||||||
|
topPadding: Dp,
|
||||||
|
bottomPadding: Dp
|
||||||
|
) {
|
||||||
|
SettingsSubcategory(
|
||||||
|
titleColor = titleColor,
|
||||||
|
title = title,
|
||||||
|
showTitle = showTitle,
|
||||||
|
showDivider = showDivider,
|
||||||
|
topPadding = topPadding,
|
||||||
|
bottomPadding = bottomPadding
|
||||||
|
) {
|
||||||
|
item {
|
||||||
|
HorizontalGestureOption()
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
HorizontalGestureScrollOption()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package ua.acclorite.book_story.presentation.settings.reader.reading_mode.components
|
||||||
|
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
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.domain.reader.ReaderHorizontalGesture
|
||||||
|
import ua.acclorite.book_story.domain.ui.ButtonItem
|
||||||
|
import ua.acclorite.book_story.presentation.core.components.settings.ChipsWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.main.MainEvent
|
||||||
|
import ua.acclorite.book_story.ui.main.MainModel
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun HorizontalGestureOption() {
|
||||||
|
val mainModel = hiltViewModel<MainModel>()
|
||||||
|
val state = mainModel.state.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
|
ChipsWithTitle(
|
||||||
|
title = stringResource(id = R.string.horizontal_gesture_option),
|
||||||
|
chips = ReaderHorizontalGesture.entries.map {
|
||||||
|
ButtonItem(
|
||||||
|
id = it.toString(),
|
||||||
|
title = when (it) {
|
||||||
|
ReaderHorizontalGesture.OFF -> {
|
||||||
|
stringResource(R.string.horizontal_gesture_off)
|
||||||
|
}
|
||||||
|
|
||||||
|
ReaderHorizontalGesture.ON -> {
|
||||||
|
stringResource(R.string.horizontal_gesture_on)
|
||||||
|
}
|
||||||
|
|
||||||
|
ReaderHorizontalGesture.INVERSE -> {
|
||||||
|
stringResource(R.string.horizontal_gesture_inverse)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
textStyle = MaterialTheme.typography.labelLarge,
|
||||||
|
selected = it == state.value.horizontalGesture
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
mainModel.onEvent(
|
||||||
|
MainEvent.OnChangeHorizontalGesture(
|
||||||
|
it.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package ua.acclorite.book_story.presentation.settings.reader.reading_mode.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.domain.reader.ReaderHorizontalGesture
|
||||||
|
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 HorizontalGestureScrollOption() {
|
||||||
|
val mainModel = hiltViewModel<MainModel>()
|
||||||
|
val state = mainModel.state.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
|
ExpandingTransition(
|
||||||
|
visible = when (state.value.horizontalGesture) {
|
||||||
|
ReaderHorizontalGesture.OFF -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
SliderWithTitle(
|
||||||
|
value = state.value.horizontalGestureScroll to "%",
|
||||||
|
toValue = 100,
|
||||||
|
title = stringResource(id = R.string.horizontal_gesture_scroll_option),
|
||||||
|
onValueChange = {
|
||||||
|
mainModel.onEvent(
|
||||||
|
MainEvent.OnChangeHorizontalGestureScroll(it)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -45,4 +45,6 @@ sealed class MainEvent {
|
||||||
data class OnChangeScreenOrientation(val value: String) : MainEvent()
|
data class OnChangeScreenOrientation(val value: String) : MainEvent()
|
||||||
data class OnChangeCustomScreenBrightness(val value: Boolean) : MainEvent()
|
data class OnChangeCustomScreenBrightness(val value: Boolean) : MainEvent()
|
||||||
data class OnChangeScreenBrightness(val value: Float) : MainEvent()
|
data class OnChangeScreenBrightness(val value: Float) : MainEvent()
|
||||||
|
data class OnChangeHorizontalGesture(val value: String) : MainEvent()
|
||||||
|
data class OnChangeHorizontalGestureScroll(val value: Float) : MainEvent()
|
||||||
}
|
}
|
||||||
|
|
@ -17,6 +17,7 @@ import kotlinx.coroutines.withContext
|
||||||
import ua.acclorite.book_story.domain.browse.toBrowseFilesStructure
|
import ua.acclorite.book_story.domain.browse.toBrowseFilesStructure
|
||||||
import ua.acclorite.book_story.domain.browse.toBrowseLayout
|
import ua.acclorite.book_story.domain.browse.toBrowseLayout
|
||||||
import ua.acclorite.book_story.domain.browse.toBrowseSortOrder
|
import ua.acclorite.book_story.domain.browse.toBrowseSortOrder
|
||||||
|
import ua.acclorite.book_story.domain.reader.toHorizontalGesture
|
||||||
import ua.acclorite.book_story.domain.reader.toReaderScreenOrientation
|
import ua.acclorite.book_story.domain.reader.toReaderScreenOrientation
|
||||||
import ua.acclorite.book_story.domain.reader.toTextAlignment
|
import ua.acclorite.book_story.domain.reader.toTextAlignment
|
||||||
import ua.acclorite.book_story.domain.use_case.data_store.ChangeLanguage
|
import ua.acclorite.book_story.domain.use_case.data_store.ChangeLanguage
|
||||||
|
|
@ -377,6 +378,22 @@ class MainModel @Inject constructor(
|
||||||
it.copy(screenBrightness = this.toFloat())
|
it.copy(screenBrightness = this.toFloat())
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
is MainEvent.OnChangeHorizontalGesture -> handleDatastoreUpdate(
|
||||||
|
key = DataStoreConstants.HORIZONTAL_GESTURE,
|
||||||
|
value = event.value,
|
||||||
|
updateState = {
|
||||||
|
it.copy(horizontalGesture = toHorizontalGesture())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
is MainEvent.OnChangeHorizontalGestureScroll -> handleDatastoreUpdate(
|
||||||
|
key = DataStoreConstants.HORIZONTAL_GESTURE_SCROLL,
|
||||||
|
value = event.value.toDouble(),
|
||||||
|
updateState = {
|
||||||
|
it.copy(horizontalGestureScroll = this.toFloat())
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,10 @@ import ua.acclorite.book_story.domain.browse.BrowseSortOrder
|
||||||
import ua.acclorite.book_story.domain.browse.toBrowseFilesStructure
|
import ua.acclorite.book_story.domain.browse.toBrowseFilesStructure
|
||||||
import ua.acclorite.book_story.domain.browse.toBrowseLayout
|
import ua.acclorite.book_story.domain.browse.toBrowseLayout
|
||||||
import ua.acclorite.book_story.domain.browse.toBrowseSortOrder
|
import ua.acclorite.book_story.domain.browse.toBrowseSortOrder
|
||||||
|
import ua.acclorite.book_story.domain.reader.ReaderHorizontalGesture
|
||||||
import ua.acclorite.book_story.domain.reader.ReaderScreenOrientation
|
import ua.acclorite.book_story.domain.reader.ReaderScreenOrientation
|
||||||
import ua.acclorite.book_story.domain.reader.ReaderTextAlignment
|
import ua.acclorite.book_story.domain.reader.ReaderTextAlignment
|
||||||
|
import ua.acclorite.book_story.domain.reader.toHorizontalGesture
|
||||||
import ua.acclorite.book_story.domain.reader.toReaderScreenOrientation
|
import ua.acclorite.book_story.domain.reader.toReaderScreenOrientation
|
||||||
import ua.acclorite.book_story.domain.reader.toTextAlignment
|
import ua.acclorite.book_story.domain.reader.toTextAlignment
|
||||||
import ua.acclorite.book_story.presentation.core.constants.Constants
|
import ua.acclorite.book_story.presentation.core.constants.Constants
|
||||||
|
|
@ -84,6 +86,10 @@ data class MainState(
|
||||||
},
|
},
|
||||||
val customScreenBrightness: Boolean = provideDefaultValue { false },
|
val customScreenBrightness: Boolean = provideDefaultValue { false },
|
||||||
val screenBrightness: Float = provideDefaultValue { 0.5f },
|
val screenBrightness: Float = provideDefaultValue { 0.5f },
|
||||||
|
val horizontalGesture: ReaderHorizontalGesture = provideDefaultValue {
|
||||||
|
ReaderHorizontalGesture.OFF
|
||||||
|
},
|
||||||
|
val horizontalGestureScroll: Float = provideDefaultValue { 0.7f },
|
||||||
|
|
||||||
// Browse Settings
|
// Browse Settings
|
||||||
val browseFilesStructure: BrowseFilesStructure = provideDefaultValue {
|
val browseFilesStructure: BrowseFilesStructure = provideDefaultValue {
|
||||||
|
|
@ -281,6 +287,14 @@ data class MainState(
|
||||||
screenBrightness = provideValue(
|
screenBrightness = provideValue(
|
||||||
SCREEN_BRIGHTNESS, convert = { this.toFloat() }
|
SCREEN_BRIGHTNESS, convert = { this.toFloat() }
|
||||||
) { screenBrightness },
|
) { screenBrightness },
|
||||||
|
|
||||||
|
horizontalGesture = provideValue(
|
||||||
|
HORIZONTAL_GESTURE, convert = { toHorizontalGesture() }
|
||||||
|
) { horizontalGesture },
|
||||||
|
|
||||||
|
horizontalGestureScroll = provideValue(
|
||||||
|
HORIZONTAL_GESTURE_SCROLL, convert = { toFloat() }
|
||||||
|
) { horizontalGestureScroll },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -316,6 +316,8 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
chapters = chapters,
|
chapters = chapters,
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
verticalPadding = verticalPadding,
|
verticalPadding = verticalPadding,
|
||||||
|
horizontalGesture = mainState.value.horizontalGesture,
|
||||||
|
horizontalGestureScroll = mainState.value.horizontalGestureScroll,
|
||||||
paragraphHeight = paragraphHeight,
|
paragraphHeight = paragraphHeight,
|
||||||
sidePadding = sidePadding,
|
sidePadding = sidePadding,
|
||||||
backgroundColor = backgroundColor.value,
|
backgroundColor = backgroundColor.value,
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,7 @@
|
||||||
<string name="padding_reader_settings">Відступи</string>
|
<string name="padding_reader_settings">Відступи</string>
|
||||||
<string name="misc_reader_settings">Інше</string>
|
<string name="misc_reader_settings">Інше</string>
|
||||||
<string name="reading_speed_reader_settings">Швидкість читання</string>
|
<string name="reading_speed_reader_settings">Швидкість читання</string>
|
||||||
|
<string name="reading_mode_reader_settings">Режим читання</string>
|
||||||
<string name="system_reader_settings">Система</string>
|
<string name="system_reader_settings">Система</string>
|
||||||
<string name="theme_appearance_settings">Налаштування теми</string>
|
<string name="theme_appearance_settings">Налаштування теми</string>
|
||||||
<string name="colors_appearance_settings">Кольори</string>
|
<string name="colors_appearance_settings">Кольори</string>
|
||||||
|
|
@ -264,6 +265,8 @@
|
||||||
<string name="screen_orientation_option">Орієнтація екрана</string>
|
<string name="screen_orientation_option">Орієнтація екрана</string>
|
||||||
<string name="custom_screen_brightness_option">Користувацька яскравість</string>
|
<string name="custom_screen_brightness_option">Користувацька яскравість</string>
|
||||||
<string name="screen_brightness_option">Яскравість</string>
|
<string name="screen_brightness_option">Яскравість</string>
|
||||||
|
<string name="horizontal_gesture_option">Горизонтальний жест</string>
|
||||||
|
<string name="horizontal_gesture_scroll_option">Частка прокрутки</string>
|
||||||
|
|
||||||
<!-- Browse -->
|
<!-- Browse -->
|
||||||
<string name="browse_files_structure_option">Структура файлів</string>
|
<string name="browse_files_structure_option">Структура файлів</string>
|
||||||
|
|
@ -331,6 +334,11 @@
|
||||||
<string name="screen_orientation_locked_portrait">Заблокований портрет</string>
|
<string name="screen_orientation_locked_portrait">Заблокований портрет</string>
|
||||||
<string name="screen_orientation_locked_landscape">Заблокований альбом</string>
|
<string name="screen_orientation_locked_landscape">Заблокований альбом</string>
|
||||||
|
|
||||||
|
<!-- Horizontal Gesture properties -->
|
||||||
|
<string name="horizontal_gesture_off">Вимкнений</string>
|
||||||
|
<string name="horizontal_gesture_on">Ввімкнений</string>
|
||||||
|
<string name="horizontal_gesture_inverse">Ввімкнений (Інвертований)</string>
|
||||||
|
|
||||||
<!-- Themes -->
|
<!-- Themes -->
|
||||||
<string name="dynamic_theme">Меркурій</string>
|
<string name="dynamic_theme">Меркурій</string>
|
||||||
<string name="blue_theme">Нептун</string>
|
<string name="blue_theme">Нептун</string>
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,7 @@
|
||||||
<string name="padding_reader_settings">Padding</string>
|
<string name="padding_reader_settings">Padding</string>
|
||||||
<string name="misc_reader_settings">Misc</string>
|
<string name="misc_reader_settings">Misc</string>
|
||||||
<string name="reading_speed_reader_settings">Reading speed</string>
|
<string name="reading_speed_reader_settings">Reading speed</string>
|
||||||
|
<string name="reading_mode_reader_settings">Reading mode</string>
|
||||||
<string name="system_reader_settings">System</string>
|
<string name="system_reader_settings">System</string>
|
||||||
<string name="theme_appearance_settings">Theme preferences</string>
|
<string name="theme_appearance_settings">Theme preferences</string>
|
||||||
<string name="colors_appearance_settings">Colors</string>
|
<string name="colors_appearance_settings">Colors</string>
|
||||||
|
|
@ -265,6 +266,8 @@
|
||||||
<string name="screen_orientation_option">Screen orientation</string>
|
<string name="screen_orientation_option">Screen orientation</string>
|
||||||
<string name="custom_screen_brightness_option">Custom brightness</string>
|
<string name="custom_screen_brightness_option">Custom brightness</string>
|
||||||
<string name="screen_brightness_option">Brightness</string>
|
<string name="screen_brightness_option">Brightness</string>
|
||||||
|
<string name="horizontal_gesture_option">Horizontal gesture</string>
|
||||||
|
<string name="horizontal_gesture_scroll_option">Scroll fraction</string>
|
||||||
|
|
||||||
<!-- Browse -->
|
<!-- Browse -->
|
||||||
<string name="browse_files_structure_option">Files structure</string>
|
<string name="browse_files_structure_option">Files structure</string>
|
||||||
|
|
@ -332,6 +335,11 @@
|
||||||
<string name="screen_orientation_locked_portrait">Locked portrait</string>
|
<string name="screen_orientation_locked_portrait">Locked portrait</string>
|
||||||
<string name="screen_orientation_locked_landscape">Locked landscape</string>
|
<string name="screen_orientation_locked_landscape">Locked landscape</string>
|
||||||
|
|
||||||
|
<!-- Horizontal Gesture properties -->
|
||||||
|
<string name="horizontal_gesture_off">Off</string>
|
||||||
|
<string name="horizontal_gesture_on">On</string>
|
||||||
|
<string name="horizontal_gesture_inverse">On (Inverse)</string>
|
||||||
|
|
||||||
<!-- Themes -->
|
<!-- Themes -->
|
||||||
<string name="dynamic_theme">Mercury</string>
|
<string name="dynamic_theme">Mercury</string>
|
||||||
<string name="blue_theme">Neptune</string>
|
<string name="blue_theme">Neptune</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue