🚀 Fullscreen option
* Added "Fullscreen" option in Reader * If true, hides system bars and removes padding * Placed in "Misc" subcategory
This commit is contained in:
parent
3de024457b
commit
5d7f3e09ac
14 changed files with 273 additions and 32 deletions
|
|
@ -30,6 +30,7 @@ object DataStoreConstants {
|
||||||
val TEXT_ALIGNMENT = stringPreferencesKey("text_alignment")
|
val TEXT_ALIGNMENT = stringPreferencesKey("text_alignment")
|
||||||
val LETTER_SPACING = intPreferencesKey("letter_spacing")
|
val LETTER_SPACING = intPreferencesKey("letter_spacing")
|
||||||
val CUTOUT_PADDING = booleanPreferencesKey("cutout_padding")
|
val CUTOUT_PADDING = booleanPreferencesKey("cutout_padding")
|
||||||
|
val FULLSCREEN = booleanPreferencesKey("fullscreen")
|
||||||
|
|
||||||
// Browse settings
|
// Browse settings
|
||||||
val BROWSE_FILES_STRUCTURE = stringPreferencesKey("browse_files_structure")
|
val BROWSE_FILES_STRUCTURE = stringPreferencesKey("browse_files_structure")
|
||||||
|
|
|
||||||
|
|
@ -33,4 +33,5 @@ sealed class MainEvent {
|
||||||
data class OnChangeLetterSpacing(val spacing: Int) : MainEvent()
|
data class OnChangeLetterSpacing(val spacing: Int) : MainEvent()
|
||||||
data class OnChangeAbsoluteDark(val bool: Boolean) : MainEvent()
|
data class OnChangeAbsoluteDark(val bool: Boolean) : MainEvent()
|
||||||
data class OnChangeCutoutPadding(val bool: Boolean) : MainEvent()
|
data class OnChangeCutoutPadding(val bool: Boolean) : MainEvent()
|
||||||
|
data class OnChangeFullscreen(val bool: Boolean) : MainEvent()
|
||||||
}
|
}
|
||||||
|
|
@ -70,6 +70,7 @@ data class MainState(
|
||||||
val textAlignment: ReaderTextAlignment = provideDefaultValue { ReaderTextAlignment.START },
|
val textAlignment: ReaderTextAlignment = provideDefaultValue { ReaderTextAlignment.START },
|
||||||
val letterSpacing: Int = provideDefaultValue { 0 },
|
val letterSpacing: Int = provideDefaultValue { 0 },
|
||||||
val cutoutPadding: Boolean = provideDefaultValue { false },
|
val cutoutPadding: Boolean = provideDefaultValue { false },
|
||||||
|
val fullscreen: Boolean = provideDefaultValue { true },
|
||||||
|
|
||||||
// Browse Settings
|
// Browse Settings
|
||||||
val browseFilesStructure: BrowseFilesStructure = provideDefaultValue {
|
val browseFilesStructure: BrowseFilesStructure = provideDefaultValue {
|
||||||
|
|
@ -219,6 +220,10 @@ data class MainState(
|
||||||
cutoutPadding = provideValue(
|
cutoutPadding = provideValue(
|
||||||
CUTOUT_PADDING
|
CUTOUT_PADDING
|
||||||
) { cutoutPadding },
|
) { cutoutPadding },
|
||||||
|
|
||||||
|
fullscreen = provideValue(
|
||||||
|
FULLSCREEN
|
||||||
|
) { fullscreen },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,6 +401,20 @@ class MainViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is MainEvent.OnChangeFullscreen -> {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
setDatastore.execute(
|
||||||
|
DataStoreConstants.FULLSCREEN,
|
||||||
|
event.bool
|
||||||
|
)
|
||||||
|
updateStateWithSavedHandle {
|
||||||
|
it.copy(
|
||||||
|
fullscreen = event.bool
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,19 @@ import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.asPaddingValues
|
import androidx.compose.foundation.layout.asPaddingValues
|
||||||
|
import androidx.compose.foundation.layout.calculateEndPadding
|
||||||
|
import androidx.compose.foundation.layout.calculateStartPadding
|
||||||
import androidx.compose.foundation.layout.displayCutout
|
import androidx.compose.foundation.layout.displayCutout
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.systemBarsIgnoringVisibility
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.material3.LinearProgressIndicator
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
|
|
@ -42,6 +46,8 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
|
|
@ -78,6 +84,8 @@ import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderScreenRoot(screen: Screen.Reader) {
|
fun ReaderScreenRoot(screen: Screen.Reader) {
|
||||||
val state = LocalReaderViewModel.current.state
|
val state = LocalReaderViewModel.current.state
|
||||||
|
val mainState = LocalMainViewModel.current.state
|
||||||
|
val onEvent = LocalReaderViewModel.current.onEvent
|
||||||
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
val viewModel = LocalReaderViewModel.current.viewModel
|
val viewModel = LocalReaderViewModel.current.viewModel
|
||||||
|
|
@ -101,7 +109,8 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
|
||||||
viewModel.init(
|
viewModel.init(
|
||||||
screen = screen,
|
screen = screen,
|
||||||
onNavigate = onNavigate,
|
onNavigate = onNavigate,
|
||||||
context = context,
|
fullscreenMode = mainState.value.fullscreen,
|
||||||
|
activity = context,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryEvent(HistoryEvent.OnLoadList)
|
onHistoryEvent(HistoryEvent.OnLoadList)
|
||||||
|
|
@ -114,9 +123,23 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
|
||||||
}
|
}
|
||||||
LaunchedEffect(canScroll) {
|
LaunchedEffect(canScroll) {
|
||||||
if (!canScroll && !state.value.showMenu && !state.value.loading) {
|
if (!canScroll && !state.value.showMenu && !state.value.loading) {
|
||||||
viewModel.onEvent(ReaderEvent.OnShowHideMenu(context = context))
|
onEvent(
|
||||||
|
ReaderEvent.OnShowHideMenu(
|
||||||
|
fullscreenMode = mainState.value.fullscreen,
|
||||||
|
activity = context
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LaunchedEffect(mainState.value.fullscreen) {
|
||||||
|
onEvent(
|
||||||
|
ReaderEvent.OnShowHideMenu(
|
||||||
|
show = state.value.showMenu,
|
||||||
|
fullscreenMode = mainState.value.fullscreen,
|
||||||
|
activity = context
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
LaunchedEffect(lazyListState) {
|
LaunchedEffect(lazyListState) {
|
||||||
viewModel.onUpdateProgress {
|
viewModel.onUpdateProgress {
|
||||||
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
|
|
@ -138,6 +161,7 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
||||||
@Composable
|
@Composable
|
||||||
private fun ReaderScreen(lazyListState: LazyListState) {
|
private fun ReaderScreen(lazyListState: LazyListState) {
|
||||||
|
|
@ -160,7 +184,12 @@ private fun ReaderScreen(lazyListState: LazyListState) {
|
||||||
val velocity = consumed.y
|
val velocity = consumed.y
|
||||||
|
|
||||||
if ((velocity > 70 || velocity < -70) && state.value.showMenu && !state.value.lockMenu) {
|
if ((velocity > 70 || velocity < -70) && state.value.showMenu && !state.value.lockMenu) {
|
||||||
onEvent(ReaderEvent.OnShowHideMenu(context = context))
|
onEvent(
|
||||||
|
ReaderEvent.OnShowHideMenu(
|
||||||
|
fullscreenMode = mainState.value.fullscreen,
|
||||||
|
activity = context
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onPostScroll(consumed, available, source)
|
return super.onPostScroll(consumed, available, source)
|
||||||
|
|
@ -203,6 +232,64 @@ private fun ReaderScreen(lazyListState: LazyListState) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val density = LocalDensity.current
|
||||||
|
val layoutDirection = LocalLayoutDirection.current
|
||||||
|
val cutoutInsets = WindowInsets.displayCutout
|
||||||
|
val systemBarsInsets = WindowInsets.systemBarsIgnoringVisibility
|
||||||
|
|
||||||
|
val cutoutInsetsPadding = remember(mainState.value.cutoutPadding) {
|
||||||
|
derivedStateOf {
|
||||||
|
cutoutInsets.asPaddingValues(density = density).run {
|
||||||
|
if (mainState.value.cutoutPadding) PaddingValues(
|
||||||
|
top = calculateTopPadding(),
|
||||||
|
start = calculateStartPadding(layoutDirection),
|
||||||
|
end = calculateEndPadding(layoutDirection),
|
||||||
|
bottom = calculateBottomPadding()
|
||||||
|
) else PaddingValues(0.dp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val systemBarsInsetsPadding = remember(mainState.value.fullscreen) {
|
||||||
|
derivedStateOf {
|
||||||
|
systemBarsInsets.asPaddingValues(density = density).run {
|
||||||
|
if (!mainState.value.fullscreen) PaddingValues(
|
||||||
|
top = calculateTopPadding(),
|
||||||
|
start = calculateStartPadding(layoutDirection),
|
||||||
|
end = calculateEndPadding(layoutDirection),
|
||||||
|
bottom = calculateBottomPadding()
|
||||||
|
) else PaddingValues(0.dp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val contentPadding = remember(
|
||||||
|
cutoutInsetsPadding.value,
|
||||||
|
systemBarsInsetsPadding.value
|
||||||
|
) {
|
||||||
|
PaddingValues(
|
||||||
|
top = systemBarsInsetsPadding.value.calculateTopPadding().run {
|
||||||
|
if (equals(0.dp)) return@run cutoutInsetsPadding.value
|
||||||
|
.calculateTopPadding()
|
||||||
|
this
|
||||||
|
},
|
||||||
|
start = systemBarsInsetsPadding.value.calculateStartPadding(layoutDirection).run {
|
||||||
|
if (equals(0.dp)) return@run cutoutInsetsPadding.value
|
||||||
|
.calculateStartPadding(layoutDirection)
|
||||||
|
this
|
||||||
|
},
|
||||||
|
end = systemBarsInsetsPadding.value.calculateEndPadding(layoutDirection).run {
|
||||||
|
if (equals(0.dp)) return@run cutoutInsetsPadding.value
|
||||||
|
.calculateEndPadding(layoutDirection)
|
||||||
|
this
|
||||||
|
},
|
||||||
|
bottom = systemBarsInsetsPadding.value.calculateBottomPadding().run {
|
||||||
|
if (equals(0.dp)) return@run cutoutInsetsPadding.value
|
||||||
|
.calculateBottomPadding()
|
||||||
|
this
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (state.value.showSettingsBottomSheet) {
|
if (state.value.showSettingsBottomSheet) {
|
||||||
ReaderSettingsBottomSheet()
|
ReaderSettingsBottomSheet()
|
||||||
}
|
}
|
||||||
|
|
@ -302,7 +389,10 @@ private fun ReaderScreen(lazyListState: LazyListState) {
|
||||||
indication = null,
|
indication = null,
|
||||||
onClick = {
|
onClick = {
|
||||||
onEvent(
|
onEvent(
|
||||||
ReaderEvent.OnShowHideMenu(context = context)
|
ReaderEvent.OnShowHideMenu(
|
||||||
|
fullscreenMode = mainState.value.fullscreen,
|
||||||
|
activity = context
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -325,11 +415,7 @@ private fun ReaderScreen(lazyListState: LazyListState) {
|
||||||
.showToast(context = context, longToast = false)
|
.showToast(context = context, longToast = false)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(
|
.padding(contentPadding),
|
||||||
if (mainState.value.cutoutPadding) Modifier.padding(
|
|
||||||
WindowInsets.displayCutout.asPaddingValues()
|
|
||||||
) else Modifier
|
|
||||||
),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(paragraphHeight),
|
verticalArrangement = Arrangement.spacedBy(paragraphHeight),
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
top = (WindowInsets.displayCutout.asPaddingValues()
|
top = (WindowInsets.displayCutout.asPaddingValues()
|
||||||
|
|
@ -355,6 +441,7 @@ private fun ReaderScreen(lazyListState: LazyListState) {
|
||||||
letterSpacing = letterSpacing,
|
letterSpacing = letterSpacing,
|
||||||
sidePadding = sidePadding,
|
sidePadding = sidePadding,
|
||||||
paragraphIndentation = mainState.value.paragraphIndentation,
|
paragraphIndentation = mainState.value.paragraphIndentation,
|
||||||
|
fullscreenMode = mainState.value.fullscreen,
|
||||||
doubleClickTranslationEnabled = mainState.value.doubleClickTranslation,
|
doubleClickTranslationEnabled = mainState.value.doubleClickTranslation,
|
||||||
toolbarHidden = toolbarHidden
|
toolbarHidden = toolbarHidden
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.
|
||||||
* @param letterSpacing Letter spacing.
|
* @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 fullscreenMode Whether Reader is in fullscreen mode.
|
||||||
* @param doubleClickTranslationEnabled Whether Double Click Translation is enabled.
|
* @param doubleClickTranslationEnabled Whether Double Click Translation is enabled.
|
||||||
* @param toolbarHidden Whether selection toolBar is hidden.
|
* @param toolbarHidden Whether selection toolBar is hidden.
|
||||||
*/
|
*/
|
||||||
|
|
@ -59,6 +60,7 @@ fun LazyItemScope.ReaderTextParagraph(
|
||||||
letterSpacing: TextUnit,
|
letterSpacing: TextUnit,
|
||||||
sidePadding: Dp,
|
sidePadding: Dp,
|
||||||
paragraphIndentation: Boolean,
|
paragraphIndentation: Boolean,
|
||||||
|
fullscreenMode: Boolean,
|
||||||
doubleClickTranslationEnabled: Boolean,
|
doubleClickTranslationEnabled: Boolean,
|
||||||
toolbarHidden: Boolean
|
toolbarHidden: Boolean
|
||||||
) {
|
) {
|
||||||
|
|
@ -109,7 +111,10 @@ fun LazyItemScope.ReaderTextParagraph(
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
onEvent(
|
onEvent(
|
||||||
ReaderEvent.OnShowHideMenu(context = context as ComponentActivity)
|
ReaderEvent.OnShowHideMenu(
|
||||||
|
fullscreenMode = fullscreenMode,
|
||||||
|
activity = context as ComponentActivity
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,13 @@ 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.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
|
||||||
import ua.acclorite.book_story.presentation.core.components.LocalReaderViewModel
|
import ua.acclorite.book_story.presentation.core.components.LocalReaderViewModel
|
||||||
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet
|
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet
|
||||||
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.nested.appearance.components.subcategories.ColorsSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ColorsSubcategory
|
||||||
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.FontSubcategory
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.MiscSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.PaddingSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.PaddingSubcategory
|
||||||
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.TextSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TranslatorSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TranslatorSubcategory
|
||||||
|
|
@ -36,6 +38,7 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.compo
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderSettingsBottomSheet() {
|
fun ReaderSettingsBottomSheet() {
|
||||||
val state = LocalReaderViewModel.current.state
|
val state = LocalReaderViewModel.current.state
|
||||||
|
val mainState = LocalMainViewModel.current.state
|
||||||
val onEvent = LocalReaderViewModel.current.onEvent
|
val onEvent = LocalReaderViewModel.current.onEvent
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
|
@ -61,6 +64,7 @@ fun ReaderSettingsBottomSheet() {
|
||||||
onEvent(
|
onEvent(
|
||||||
ReaderEvent.OnShowHideMenu(
|
ReaderEvent.OnShowHideMenu(
|
||||||
pagerState.currentPage != 2,
|
pagerState.currentPage != 2,
|
||||||
|
fullscreenMode = mainState.value.fullscreen,
|
||||||
context as ComponentActivity
|
context as ComponentActivity
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -87,6 +91,11 @@ fun ReaderSettingsBottomSheet() {
|
||||||
topPadding = 22.dp,
|
topPadding = 22.dp,
|
||||||
bottomPadding = 0.dp
|
bottomPadding = 0.dp
|
||||||
)
|
)
|
||||||
|
MiscSubcategory(
|
||||||
|
titleColor = { MaterialTheme.colorScheme.onSurface },
|
||||||
|
topPadding = 22.dp,
|
||||||
|
bottomPadding = 8.dp + it
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ sealed class ReaderEvent {
|
||||||
|
|
||||||
data class OnShowHideMenu(
|
data class OnShowHideMenu(
|
||||||
val show: Boolean? = null,
|
val show: Boolean? = null,
|
||||||
val context: ComponentActivity
|
val fullscreenMode: Boolean,
|
||||||
|
val activity: ComponentActivity
|
||||||
) : ReaderEvent()
|
) : ReaderEvent()
|
||||||
|
|
||||||
data class OnGoBack(
|
data class OnGoBack(
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.debounce
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.coroutines.yield
|
import kotlinx.coroutines.yield
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.domain.model.Book
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
|
@ -153,21 +154,11 @@ class ReaderViewModel @Inject constructor(
|
||||||
|
|
||||||
yield()
|
yield()
|
||||||
|
|
||||||
WindowCompat.getInsetsController(
|
showSystemBars(
|
||||||
event.context.window,
|
show = shouldShow,
|
||||||
event.context.window.decorView
|
fullscreenMode = event.fullscreenMode,
|
||||||
).apply {
|
activity = event.activity
|
||||||
yield()
|
)
|
||||||
|
|
||||||
systemBarsBehavior = WindowInsetsControllerCompat
|
|
||||||
.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
|
||||||
if (shouldShow) {
|
|
||||||
show(WindowInsetsCompat.Type.systemBars())
|
|
||||||
} else {
|
|
||||||
hide(WindowInsetsCompat.Type.systemBars())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
showMenu = shouldShow
|
showMenu = shouldShow
|
||||||
|
|
@ -405,7 +396,8 @@ class ReaderViewModel @Inject constructor(
|
||||||
fun init(
|
fun init(
|
||||||
screen: Screen.Reader,
|
screen: Screen.Reader,
|
||||||
onNavigate: OnNavigate,
|
onNavigate: OnNavigate,
|
||||||
context: ComponentActivity,
|
fullscreenMode: Boolean,
|
||||||
|
activity: ComponentActivity,
|
||||||
refreshList: (Book) -> Unit,
|
refreshList: (Book) -> Unit,
|
||||||
onError: (UIText) -> Unit
|
onError: (UIText) -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
@ -425,10 +417,17 @@ class ReaderViewModel @Inject constructor(
|
||||||
|
|
||||||
clear()
|
clear()
|
||||||
launch {
|
launch {
|
||||||
launch(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
context.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
activity.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
}.join()
|
}
|
||||||
onEvent(ReaderEvent.OnShowHideMenu(false, context))
|
|
||||||
|
onEvent(
|
||||||
|
ReaderEvent.OnShowHideMenu(
|
||||||
|
show = false,
|
||||||
|
fullscreenMode = fullscreenMode,
|
||||||
|
activity = activity
|
||||||
|
)
|
||||||
|
)
|
||||||
onEvent(
|
onEvent(
|
||||||
ReaderEvent.OnLoadText(
|
ReaderEvent.OnLoadText(
|
||||||
refreshList = { refreshList(it) },
|
refreshList = { refreshList(it) },
|
||||||
|
|
@ -495,6 +494,23 @@ class ReaderViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showSystemBars(
|
||||||
|
show: Boolean,
|
||||||
|
fullscreenMode: Boolean,
|
||||||
|
activity: ComponentActivity
|
||||||
|
): Boolean {
|
||||||
|
WindowCompat.getInsetsController(
|
||||||
|
activity.window,
|
||||||
|
activity.window.decorView
|
||||||
|
).apply {
|
||||||
|
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
|
if (show || !fullscreenMode) show(WindowInsetsCompat.Type.systemBars())
|
||||||
|
else hide(WindowInsetsCompat.Type.systemBars())
|
||||||
|
}
|
||||||
|
|
||||||
|
return show || !fullscreenMode
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun clear() {
|
private suspend fun clear() {
|
||||||
eventJob.cancel()
|
eventJob.cancel()
|
||||||
eventJob.join()
|
eventJob.join()
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.presentation.core.components.CategoryTitle
|
import ua.acclorite.book_story.presentation.core.components.CategoryTitle
|
||||||
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.FontSubcategory
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.MiscSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.PaddingSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.PaddingSubcategory
|
||||||
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.TextSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TranslatorSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TranslatorSubcategory
|
||||||
|
|
@ -43,6 +44,11 @@ fun LazyListScope.ReaderSettingsCategory(
|
||||||
bottomPadding = 0.dp
|
bottomPadding = 0.dp
|
||||||
)
|
)
|
||||||
TranslatorSubcategory(
|
TranslatorSubcategory(
|
||||||
|
titleColor = titleColor,
|
||||||
|
topPadding = 22.dp,
|
||||||
|
bottomPadding = 0.dp
|
||||||
|
)
|
||||||
|
MiscSubcategory(
|
||||||
titleColor = titleColor,
|
titleColor = titleColor,
|
||||||
topPadding = 22.dp,
|
topPadding = 22.dp,
|
||||||
bottomPadding = bottomPadding
|
bottomPadding = bottomPadding
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fullscreen setting.
|
||||||
|
* If true, hides system bars in Reader.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun FullscreenSetting() {
|
||||||
|
val state = LocalMainViewModel.current.state
|
||||||
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
|
|
||||||
|
SwitchWithTitle(
|
||||||
|
selected = state.value.fullscreen,
|
||||||
|
title = stringResource(id = R.string.fullscreen_option),
|
||||||
|
description = stringResource(id = R.string.fullscreen_option_desc),
|
||||||
|
onClick = {
|
||||||
|
onMainEvent(
|
||||||
|
MainEvent.OnChangeFullscreen(
|
||||||
|
!state.value.fullscreen
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
@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.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.core.components.CategoryTitle
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.FullscreenSetting
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Misc subcategory.
|
||||||
|
* Contains all settings that cannot be categorized.
|
||||||
|
*/
|
||||||
|
fun LazyListScope.MiscSubcategory(
|
||||||
|
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||||
|
title: @Composable () -> String = { stringResource(id = R.string.misc_reader_settings) },
|
||||||
|
showTitle: Boolean = true,
|
||||||
|
topPadding: Dp,
|
||||||
|
bottomPadding: Dp
|
||||||
|
) {
|
||||||
|
item {
|
||||||
|
if (showTitle) {
|
||||||
|
CategoryTitle(
|
||||||
|
title = title.invoke(),
|
||||||
|
color = titleColor.invoke(),
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(
|
||||||
|
top = topPadding,
|
||||||
|
bottom = 8.dp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier.height((topPadding - 8.dp).coerceAtLeast(0.dp))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
FullscreenSetting()
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier.height(bottomPadding)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -200,6 +200,7 @@
|
||||||
<string name="text_reader_settings">Текст</string>
|
<string name="text_reader_settings">Текст</string>
|
||||||
<string name="translator_reader_settings">Перекладач</string>
|
<string name="translator_reader_settings">Перекладач</string>
|
||||||
<string name="padding_reader_settings">Відступи</string>
|
<string name="padding_reader_settings">Відступи</string>
|
||||||
|
<string name="misc_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>
|
||||||
<string name="general_browse_settings">Головні</string>
|
<string name="general_browse_settings">Головні</string>
|
||||||
|
|
@ -238,7 +239,9 @@
|
||||||
<string name="text_alignment_option">Розташування текста</string>
|
<string name="text_alignment_option">Розташування текста</string>
|
||||||
<string name="letter_spacing_option">Відстань між літерами</string>
|
<string name="letter_spacing_option">Відстань між літерами</string>
|
||||||
<string name="cutout_padding_option">Відступ від виїмки</string>
|
<string name="cutout_padding_option">Відступ від виїмки</string>
|
||||||
<string name="cutout_padding_option_desc">Застосуйте відступ до ділянки виїмки</string>
|
<string name="cutout_padding_option_desc">Застосувати відступ до ділянки виїмки</string>
|
||||||
|
<string name="fullscreen_option">Повний екран</string>
|
||||||
|
<string name="fullscreen_option_desc">Сховати системні панелі та прибрати відступи</string>
|
||||||
|
|
||||||
<!-- Browse -->
|
<!-- Browse -->
|
||||||
<string name="browse_files_structure_option">Структура файлів</string>
|
<string name="browse_files_structure_option">Структура файлів</string>
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@
|
||||||
<string name="text_reader_settings">Text</string>
|
<string name="text_reader_settings">Text</string>
|
||||||
<string name="translator_reader_settings">Translator</string>
|
<string name="translator_reader_settings">Translator</string>
|
||||||
<string name="padding_reader_settings">Padding</string>
|
<string name="padding_reader_settings">Padding</string>
|
||||||
|
<string name="misc_reader_settings">Misc</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>
|
||||||
<string name="general_browse_settings">General</string>
|
<string name="general_browse_settings">General</string>
|
||||||
|
|
@ -256,6 +257,8 @@
|
||||||
<string name="letter_spacing_option">Letter spacing</string>
|
<string name="letter_spacing_option">Letter spacing</string>
|
||||||
<string name="cutout_padding_option">Cutout padding</string>
|
<string name="cutout_padding_option">Cutout padding</string>
|
||||||
<string name="cutout_padding_option_desc">Apply padding to cutout area</string>
|
<string name="cutout_padding_option_desc">Apply padding to cutout area</string>
|
||||||
|
<string name="fullscreen_option">Fullscreen</string>
|
||||||
|
<string name="fullscreen_option_desc">Hide system bars and remove padding</string>
|
||||||
|
|
||||||
<!-- Browse -->
|
<!-- Browse -->
|
||||||
<string name="browse_files_structure_option">Files structure</string>
|
<string name="browse_files_structure_option">Files structure</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue