🚀 Improve ErrorPlaceholder in Reader

* Disabled onClick actions when error is shown
* Better structure
This commit is contained in:
Acclorite 2025-01-04 20:37:17 +02:00
parent cd2718b8d3
commit e93eeea497
7 changed files with 152 additions and 143 deletions

View file

@ -91,60 +91,67 @@ fun ReaderContent(
dismissBottomSheet = dismissBottomSheet
)
ReaderScaffold(
book = book,
text = text,
listState = listState,
currentChapter = currentChapter,
nestedScrollConnection = nestedScrollConnection,
fastColorPresetChange = fastColorPresetChange,
perceptionExpander = perceptionExpander,
perceptionExpanderPadding = perceptionExpanderPadding,
perceptionExpanderThickness = perceptionExpanderThickness,
currentChapterProgress = currentChapterProgress,
isLoading = isLoading,
errorMessage = errorMessage,
checkpoint = checkpoint,
showMenu = showMenu,
lockMenu = lockMenu,
contentPadding = contentPadding,
verticalPadding = verticalPadding,
horizontalGesture = horizontalGesture,
horizontalGestureScroll = horizontalGestureScroll,
horizontalGestureSensitivity = horizontalGestureSensitivity,
highlightedReading = highlightedReading,
highlightedReadingThickness = highlightedReadingThickness,
paragraphHeight = paragraphHeight,
sidePadding = sidePadding,
bottomBarPadding = bottomBarPadding,
backgroundColor = backgroundColor,
fontColor = fontColor,
fontFamily = fontFamily,
lineHeight = lineHeight,
fontStyle = fontStyle,
textAlignment = textAlignment,
horizontalAlignment = horizontalAlignment,
fontSize = fontSize,
letterSpacing = letterSpacing,
paragraphIndentation = paragraphIndentation,
doubleClickTranslation = doubleClickTranslation,
fullscreenMode = fullscreenMode,
selectPreviousPreset = selectPreviousPreset,
selectNextPreset = selectNextPreset,
menuVisibility = menuVisibility,
leave = leave,
restoreCheckpoint = restoreCheckpoint,
scroll = scroll,
changeProgress = changeProgress,
openShareApp = openShareApp,
openWebBrowser = openWebBrowser,
openTranslator = openTranslator,
openDictionary = openDictionary,
showSettingsBottomSheet = showSettingsBottomSheet,
showChaptersDrawer = showChaptersDrawer,
navigateBack = navigateBack,
navigateToBookInfo = navigateToBookInfo
)
if (isLoading || errorMessage == null) {
ReaderScaffold(
book = book,
text = text,
listState = listState,
currentChapter = currentChapter,
nestedScrollConnection = nestedScrollConnection,
fastColorPresetChange = fastColorPresetChange,
perceptionExpander = perceptionExpander,
perceptionExpanderPadding = perceptionExpanderPadding,
perceptionExpanderThickness = perceptionExpanderThickness,
currentChapterProgress = currentChapterProgress,
isLoading = isLoading,
checkpoint = checkpoint,
showMenu = showMenu,
lockMenu = lockMenu,
contentPadding = contentPadding,
verticalPadding = verticalPadding,
horizontalGesture = horizontalGesture,
horizontalGestureScroll = horizontalGestureScroll,
horizontalGestureSensitivity = horizontalGestureSensitivity,
highlightedReading = highlightedReading,
highlightedReadingThickness = highlightedReadingThickness,
paragraphHeight = paragraphHeight,
sidePadding = sidePadding,
bottomBarPadding = bottomBarPadding,
backgroundColor = backgroundColor,
fontColor = fontColor,
fontFamily = fontFamily,
lineHeight = lineHeight,
fontStyle = fontStyle,
textAlignment = textAlignment,
horizontalAlignment = horizontalAlignment,
fontSize = fontSize,
letterSpacing = letterSpacing,
paragraphIndentation = paragraphIndentation,
doubleClickTranslation = doubleClickTranslation,
fullscreenMode = fullscreenMode,
selectPreviousPreset = selectPreviousPreset,
selectNextPreset = selectNextPreset,
menuVisibility = menuVisibility,
leave = leave,
restoreCheckpoint = restoreCheckpoint,
scroll = scroll,
changeProgress = changeProgress,
openShareApp = openShareApp,
openWebBrowser = openWebBrowser,
openTranslator = openTranslator,
openDictionary = openDictionary,
showSettingsBottomSheet = showSettingsBottomSheet,
showChaptersDrawer = showChaptersDrawer,
navigateBack = navigateBack,
navigateToBookInfo = navigateToBookInfo
)
} else {
ReaderErrorPlaceholder(
errorMessage = errorMessage,
leave = leave,
navigateBack = navigateBack
)
}
ReaderDrawer(
drawer = drawer,

View file

@ -0,0 +1,47 @@
package ua.acclorite.book_story.presentation.reader
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.ui.UIText
import ua.acclorite.book_story.presentation.core.components.placeholder.ErrorPlaceholder
import ua.acclorite.book_story.presentation.core.util.LocalActivity
import ua.acclorite.book_story.ui.reader.ReaderEvent
@Composable
fun ReaderErrorPlaceholder(
errorMessage: UIText,
leave: (ReaderEvent.OnLeave) -> Unit,
navigateBack: () -> Unit
) {
val activity = LocalActivity.current
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.surface),
contentAlignment = Alignment.Center
) {
ErrorPlaceholder(
errorMessage = errorMessage.asString(),
icon = painterResource(id = R.drawable.error),
actionTitle = stringResource(id = R.string.go_back),
action = {
leave(
ReaderEvent.OnLeave(
activity = activity,
navigate = {
navigateBack()
}
)
)
}
)
}
}

View file

@ -1,61 +0,0 @@
package ua.acclorite.book_story.presentation.reader
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.ui.UIText
import ua.acclorite.book_story.presentation.core.components.placeholder.ErrorPlaceholder
import ua.acclorite.book_story.presentation.core.components.progress_indicator.CircularProgressIndicator
import ua.acclorite.book_story.presentation.core.util.LocalActivity
import ua.acclorite.book_story.ui.reader.ReaderEvent
@Composable
fun ReaderLoadingIndicator(
isLoading: Boolean,
errorMessage: UIText?,
leave: (ReaderEvent.OnLeave) -> Unit,
navigateBack: () -> Unit
) {
val activity = LocalActivity.current
if (isLoading || errorMessage != null) {
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.surface),
contentAlignment = Alignment.Center
) {
if (!isLoading) {
ErrorPlaceholder(
errorMessage = errorMessage!!.asString(),
icon = painterResource(id = R.drawable.error),
actionTitle = stringResource(id = R.string.go_back),
action = {
leave(
ReaderEvent.OnLeave(
activity = activity,
navigate = {
navigateBack()
}
)
)
}
)
} else {
CircularProgressIndicator(
modifier = Modifier.size(48.dp),
strokeWidth = 4.5.dp
)
}
}
}
}

View file

@ -0,0 +1,27 @@
package ua.acclorite.book_story.presentation.reader
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.core.components.progress_indicator.CircularProgressIndicator
@Composable
fun ReaderLoadingPlaceholder() {
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.surface),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator(
modifier = Modifier.size(48.dp),
strokeWidth = 4.5.dp
)
}
}

View file

@ -26,7 +26,6 @@ import ua.acclorite.book_story.domain.reader.ReaderHorizontalGesture
import ua.acclorite.book_story.domain.reader.ReaderText
import ua.acclorite.book_story.domain.reader.ReaderText.Chapter
import ua.acclorite.book_story.domain.reader.ReaderTextAlignment
import ua.acclorite.book_story.domain.ui.UIText
import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.ui.reader.ReaderEvent
import ua.acclorite.book_story.ui.settings.SettingsEvent
@ -45,7 +44,6 @@ fun ReaderScaffold(
perceptionExpanderThickness: Dp,
currentChapterProgress: Float,
isLoading: Boolean,
errorMessage: UIText?,
checkpoint: Checkpoint,
showMenu: Boolean,
lockMenu: Boolean,
@ -178,11 +176,8 @@ fun ReaderScaffold(
perceptionExpanderColor = fontColor
)
ReaderLoadingIndicator(
isLoading = isLoading,
errorMessage = errorMessage,
leave = leave,
navigateBack = navigateBack
)
if (isLoading) {
ReaderLoadingPlaceholder()
}
}
}

View file

@ -1,6 +1,5 @@
package ua.acclorite.book_story.ui.reader
import android.content.Context
import androidx.activity.ComponentActivity
import androidx.compose.runtime.Immutable
import ua.acclorite.book_story.domain.reader.ReaderText.Chapter
@ -8,9 +7,7 @@ import ua.acclorite.book_story.domain.reader.ReaderText.Chapter
@Immutable
sealed class ReaderEvent {
data class OnLoadText(
val context: Context
) : ReaderEvent()
data object OnLoadText : ReaderEvent()
data class OnMenuVisibility(
val show: Boolean,

View file

@ -140,8 +140,7 @@ class ReaderModel @Inject constructor(
yield()
systemBarsVisibility(
show = shouldShow,
fullscreenMode = event.fullscreenMode,
show = shouldShow || !event.fullscreenMode,
activity = event.activity
)
_state.update {
@ -482,11 +481,7 @@ class ReaderModel @Inject constructor(
activity = activity
)
)
onEvent(
ReaderEvent.OnLoadText(
context = activity
)
)
onEvent(ReaderEvent.OnLoadText)
}
}
@ -599,18 +594,20 @@ class ReaderModel @Inject constructor(
}
}
private fun systemBarsVisibility(
private suspend fun systemBarsVisibility(
show: Boolean,
fullscreenMode: Boolean,
activity: ComponentActivity
) {
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())
withContext(Dispatchers.Main) {
WindowCompat.getInsetsController(
activity.window,
activity.window.decorView
).apply {
systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
if (show) show(WindowInsetsCompat.Type.systemBars())
else hide(WindowInsetsCompat.Type.systemBars())
}
}
}