🚀 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 dismissBottomSheet = dismissBottomSheet
) )
ReaderScaffold( if (isLoading || errorMessage == null) {
book = book, ReaderScaffold(
text = text, book = book,
listState = listState, text = text,
currentChapter = currentChapter, listState = listState,
nestedScrollConnection = nestedScrollConnection, currentChapter = currentChapter,
fastColorPresetChange = fastColorPresetChange, nestedScrollConnection = nestedScrollConnection,
perceptionExpander = perceptionExpander, fastColorPresetChange = fastColorPresetChange,
perceptionExpanderPadding = perceptionExpanderPadding, perceptionExpander = perceptionExpander,
perceptionExpanderThickness = perceptionExpanderThickness, perceptionExpanderPadding = perceptionExpanderPadding,
currentChapterProgress = currentChapterProgress, perceptionExpanderThickness = perceptionExpanderThickness,
isLoading = isLoading, currentChapterProgress = currentChapterProgress,
errorMessage = errorMessage, isLoading = isLoading,
checkpoint = checkpoint, checkpoint = checkpoint,
showMenu = showMenu, showMenu = showMenu,
lockMenu = lockMenu, lockMenu = lockMenu,
contentPadding = contentPadding, contentPadding = contentPadding,
verticalPadding = verticalPadding, verticalPadding = verticalPadding,
horizontalGesture = horizontalGesture, horizontalGesture = horizontalGesture,
horizontalGestureScroll = horizontalGestureScroll, horizontalGestureScroll = horizontalGestureScroll,
horizontalGestureSensitivity = horizontalGestureSensitivity, horizontalGestureSensitivity = horizontalGestureSensitivity,
highlightedReading = highlightedReading, highlightedReading = highlightedReading,
highlightedReadingThickness = highlightedReadingThickness, highlightedReadingThickness = highlightedReadingThickness,
paragraphHeight = paragraphHeight, paragraphHeight = paragraphHeight,
sidePadding = sidePadding, sidePadding = sidePadding,
bottomBarPadding = bottomBarPadding, bottomBarPadding = bottomBarPadding,
backgroundColor = backgroundColor, backgroundColor = backgroundColor,
fontColor = fontColor, fontColor = fontColor,
fontFamily = fontFamily, fontFamily = fontFamily,
lineHeight = lineHeight, lineHeight = lineHeight,
fontStyle = fontStyle, fontStyle = fontStyle,
textAlignment = textAlignment, textAlignment = textAlignment,
horizontalAlignment = horizontalAlignment, horizontalAlignment = horizontalAlignment,
fontSize = fontSize, fontSize = fontSize,
letterSpacing = letterSpacing, letterSpacing = letterSpacing,
paragraphIndentation = paragraphIndentation, paragraphIndentation = paragraphIndentation,
doubleClickTranslation = doubleClickTranslation, doubleClickTranslation = doubleClickTranslation,
fullscreenMode = fullscreenMode, fullscreenMode = fullscreenMode,
selectPreviousPreset = selectPreviousPreset, selectPreviousPreset = selectPreviousPreset,
selectNextPreset = selectNextPreset, selectNextPreset = selectNextPreset,
menuVisibility = menuVisibility, menuVisibility = menuVisibility,
leave = leave, leave = leave,
restoreCheckpoint = restoreCheckpoint, restoreCheckpoint = restoreCheckpoint,
scroll = scroll, scroll = scroll,
changeProgress = changeProgress, changeProgress = changeProgress,
openShareApp = openShareApp, openShareApp = openShareApp,
openWebBrowser = openWebBrowser, openWebBrowser = openWebBrowser,
openTranslator = openTranslator, openTranslator = openTranslator,
openDictionary = openDictionary, openDictionary = openDictionary,
showSettingsBottomSheet = showSettingsBottomSheet, showSettingsBottomSheet = showSettingsBottomSheet,
showChaptersDrawer = showChaptersDrawer, showChaptersDrawer = showChaptersDrawer,
navigateBack = navigateBack, navigateBack = navigateBack,
navigateToBookInfo = navigateToBookInfo navigateToBookInfo = navigateToBookInfo
) )
} else {
ReaderErrorPlaceholder(
errorMessage = errorMessage,
leave = leave,
navigateBack = navigateBack
)
}
ReaderDrawer( ReaderDrawer(
drawer = drawer, 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
import ua.acclorite.book_story.domain.reader.ReaderText.Chapter import ua.acclorite.book_story.domain.reader.ReaderText.Chapter
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.presentation.core.components.common.AnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.ui.reader.ReaderEvent import ua.acclorite.book_story.ui.reader.ReaderEvent
import ua.acclorite.book_story.ui.settings.SettingsEvent import ua.acclorite.book_story.ui.settings.SettingsEvent
@ -45,7 +44,6 @@ fun ReaderScaffold(
perceptionExpanderThickness: Dp, perceptionExpanderThickness: Dp,
currentChapterProgress: Float, currentChapterProgress: Float,
isLoading: Boolean, isLoading: Boolean,
errorMessage: UIText?,
checkpoint: Checkpoint, checkpoint: Checkpoint,
showMenu: Boolean, showMenu: Boolean,
lockMenu: Boolean, lockMenu: Boolean,
@ -178,11 +176,8 @@ fun ReaderScaffold(
perceptionExpanderColor = fontColor perceptionExpanderColor = fontColor
) )
ReaderLoadingIndicator( if (isLoading) {
isLoading = isLoading, ReaderLoadingPlaceholder()
errorMessage = errorMessage, }
leave = leave,
navigateBack = navigateBack
)
} }
} }

View file

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

View file

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