feat: add loading indicator to book info's file loading

This commit is contained in:
Acclorite 2025-11-13 10:05:20 +02:00
parent 24d3e3ba0a
commit cce3f0fcea
No known key found for this signature in database
GPG key ID: 6E54C611F6EE8593
7 changed files with 36 additions and 14 deletions

View file

@ -257,7 +257,8 @@ class BookInfoModel @Inject constructor(
it.copy( it.copy(
book = it.book.copy( book = it.book.copy(
filePath = event.path filePath = event.path
) ),
loadingFile = true
) )
} }
updateBookUseCase(_state.value.book) updateBookUseCase(_state.value.book)
@ -270,7 +271,8 @@ class BookInfoModel @Inject constructor(
val file = getFileFromBookUseCase(_state.value.book.id) val file = getFileFromBookUseCase(_state.value.book.id)
_state.update { _state.update {
it.copy( it.copy(
file = file file = file,
loadingFile = false
) )
} }
} }
@ -380,7 +382,8 @@ class BookInfoModel @Inject constructor(
val file = getFileFromBookUseCase(bookId) val file = getFileFromBookUseCase(bookId)
_state.update { _state.update {
it.copy( it.copy(
file = file file = file,
loadingFile = false
) )
} }
} }

View file

@ -79,6 +79,7 @@ data class BookInfoScreen(val bookId: Int) : Screen, Parcelable {
BookInfoContent( BookInfoContent(
book = state.value.book, book = state.value.book,
file = state.value.file, file = state.value.file,
loadingFile = state.value.loadingFile,
categories = categories, categories = categories,
bottomSheet = state.value.bottomSheet, bottomSheet = state.value.bottomSheet,
dialog = state.value.dialog, dialog = state.value.dialog,

View file

@ -15,7 +15,9 @@ import ua.acclorite.book_story.domain.model.library.Book
@Immutable @Immutable
data class BookInfoState( data class BookInfoState(
val book: Book = Book.default, val book: Book = Book.default,
val file: File? = null, val file: File? = null,
val loadingFile: Boolean = true,
val canResetCover: Boolean = false, val canResetCover: Boolean = false,

View file

@ -18,6 +18,7 @@ fun BookInfoBottomSheet(
bottomSheet: BottomSheet?, bottomSheet: BottomSheet?,
book: Book, book: Book,
file: File?, file: File?,
loadingFile: Boolean,
canResetCover: Boolean, canResetCover: Boolean,
showPathDialog: (BookInfoEvent.OnShowPathDialog) -> Unit, showPathDialog: (BookInfoEvent.OnShowPathDialog) -> Unit,
changeCover: (BookInfoEvent.OnChangeCover) -> Unit, changeCover: (BookInfoEvent.OnChangeCover) -> Unit,
@ -43,6 +44,7 @@ fun BookInfoBottomSheet(
BookInfoDetailsBottomSheet( BookInfoDetailsBottomSheet(
book = book, book = book,
file = file, file = file,
loadingFile = loadingFile,
showPathDialog = showPathDialog, showPathDialog = showPathDialog,
dismissBottomSheet = dismissBottomSheet dismissBottomSheet = dismissBottomSheet
) )

View file

@ -19,6 +19,7 @@ import ua.acclorite.book_story.presentation.book_info.BookInfoEvent
fun BookInfoContent( fun BookInfoContent(
book: Book, book: Book,
file: File?, file: File?,
loadingFile: Boolean,
categories: List<Category>, categories: List<Category>,
bottomSheet: BottomSheet?, bottomSheet: BottomSheet?,
dialog: Dialog?, dialog: Dialog?,
@ -66,6 +67,7 @@ fun BookInfoContent(
bottomSheet = bottomSheet, bottomSheet = bottomSheet,
book = book, book = book,
file = file, file = file,
loadingFile = loadingFile,
showPathDialog = showPathDialog, showPathDialog = showPathDialog,
canResetCover = canResetCover, canResetCover = canResetCover,
changeCover = changeCover, changeCover = changeCover,

View file

@ -32,6 +32,7 @@ import java.util.Locale
fun BookInfoDetailsBottomSheet( fun BookInfoDetailsBottomSheet(
book: Book, book: Book,
file: File?, file: File?,
loadingFile: Boolean,
showPathDialog: (BookInfoEvent.OnShowPathDialog) -> Unit, showPathDialog: (BookInfoEvent.OnShowPathDialog) -> Unit,
dismissBottomSheet: (BookInfoEvent.OnDismissBottomSheet) -> Unit dismissBottomSheet: (BookInfoEvent.OnDismissBottomSheet) -> Unit
) { ) {
@ -53,6 +54,7 @@ fun BookInfoDetailsBottomSheet(
val fileExists = remember(file) { val fileExists = remember(file) {
file.let { file -> file.let { file ->
if (loadingFile) return@let true
if (file == null) return@let false if (file == null) return@let false
if (file.isDirectory) return@let false if (file.isDirectory) return@let false
if ( if (
@ -99,7 +101,8 @@ fun BookInfoDetailsBottomSheet(
showPathDialog(BookInfoEvent.OnShowPathDialog) showPathDialog(BookInfoEvent.OnShowPathDialog)
}, },
showError = !fileExists, showError = !fileExists,
errorMessage = stringResource(id = R.string.error_no_file) errorMessage = stringResource(id = R.string.error_no_file),
loading = loadingFile
) )
} }

View file

@ -8,6 +8,7 @@ package ua.acclorite.book_story.ui.book_info
import androidx.compose.foundation.focusable import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -15,6 +16,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.EditNote import androidx.compose.material.icons.filled.EditNote
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -25,6 +27,7 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.ui.common.components.common.IconButton import ua.acclorite.book_story.ui.common.components.common.IconButton
import ua.acclorite.book_story.ui.common.components.common.StyledText import ua.acclorite.book_story.ui.common.components.common.StyledText
import ua.acclorite.book_story.ui.theme.ExpandingTransition import ua.acclorite.book_story.ui.theme.ExpandingTransition
import ua.acclorite.book_story.ui.theme.FadeTransitionPreservingSpace
@Composable @Composable
fun BookInfoDetailsBottomSheetItem( fun BookInfoDetailsBottomSheetItem(
@ -33,6 +36,7 @@ fun BookInfoDetailsBottomSheetItem(
editable: Boolean, editable: Boolean,
showError: Boolean = false, showError: Boolean = false,
errorMessage: String? = null, errorMessage: String? = null,
loading: Boolean = false,
onEdit: () -> Unit = {} onEdit: () -> Unit = {}
) { ) {
Column( Column(
@ -55,10 +59,14 @@ fun BookInfoDetailsBottomSheetItem(
isError = showError, isError = showError,
label = { label = {
StyledText(label) StyledText(label)
} },
) )
if (editable) { Box(contentAlignment = Alignment.Center) {
FadeTransitionPreservingSpace(visible = loading) {
CircularProgressIndicator(modifier = Modifier.size(24.dp), strokeWidth = 3.2.dp)
}
FadeTransitionPreservingSpace(visible = !loading && editable) {
IconButton( IconButton(
icon = Icons.Default.EditNote, icon = Icons.Default.EditNote,
contentDescription = R.string.edit_content_desc, contentDescription = R.string.edit_content_desc,
@ -70,6 +78,7 @@ fun BookInfoDetailsBottomSheetItem(
} }
} }
} }
}
ExpandingTransition(showError && !errorMessage.isNullOrBlank()) { ExpandingTransition(showError && !errorMessage.isNullOrBlank()) {
StyledText( StyledText(