From cce3f0fceaeff47bb8d2f175a96f5dc28ba3a7f6 Mon Sep 17 00:00:00 2001 From: Acclorite <2ma0bhpk@anonaddy.com> Date: Thu, 13 Nov 2025 10:05:20 +0200 Subject: [PATCH] feat: add loading indicator to book info's file loading --- .../presentation/book_info/BookInfoModel.kt | 9 ++++-- .../presentation/book_info/BookInfoScreen.kt | 1 + .../presentation/book_info/BookInfoState.kt | 2 ++ .../ui/book_info/BookInfoBottomSheet.kt | 2 ++ .../ui/book_info/BookInfoContent.kt | 2 ++ .../book_info/BookInfoDetailsBottomSheet.kt | 5 +++- .../BookInfoDetailsBottomSheetItem.kt | 29 ++++++++++++------- 7 files changed, 36 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoModel.kt index f0dd87e7..ca74daf4 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoModel.kt @@ -257,7 +257,8 @@ class BookInfoModel @Inject constructor( it.copy( book = it.book.copy( filePath = event.path - ) + ), + loadingFile = true ) } updateBookUseCase(_state.value.book) @@ -270,7 +271,8 @@ class BookInfoModel @Inject constructor( val file = getFileFromBookUseCase(_state.value.book.id) _state.update { it.copy( - file = file + file = file, + loadingFile = false ) } } @@ -380,7 +382,8 @@ class BookInfoModel @Inject constructor( val file = getFileFromBookUseCase(bookId) _state.update { it.copy( - file = file + file = file, + loadingFile = false ) } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoScreen.kt index fa5857af..9998f1ed 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoScreen.kt @@ -79,6 +79,7 @@ data class BookInfoScreen(val bookId: Int) : Screen, Parcelable { BookInfoContent( book = state.value.book, file = state.value.file, + loadingFile = state.value.loadingFile, categories = categories, bottomSheet = state.value.bottomSheet, dialog = state.value.dialog, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoState.kt b/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoState.kt index e11b7c00..4f4842c5 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoState.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/book_info/BookInfoState.kt @@ -15,7 +15,9 @@ import ua.acclorite.book_story.domain.model.library.Book @Immutable data class BookInfoState( val book: Book = Book.default, + val file: File? = null, + val loadingFile: Boolean = true, val canResetCover: Boolean = false, diff --git a/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoBottomSheet.kt index 12c52d13..aeb77bf6 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoBottomSheet.kt @@ -18,6 +18,7 @@ fun BookInfoBottomSheet( bottomSheet: BottomSheet?, book: Book, file: File?, + loadingFile: Boolean, canResetCover: Boolean, showPathDialog: (BookInfoEvent.OnShowPathDialog) -> Unit, changeCover: (BookInfoEvent.OnChangeCover) -> Unit, @@ -43,6 +44,7 @@ fun BookInfoBottomSheet( BookInfoDetailsBottomSheet( book = book, file = file, + loadingFile = loadingFile, showPathDialog = showPathDialog, dismissBottomSheet = dismissBottomSheet ) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoContent.kt b/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoContent.kt index 915a662f..f9bf92c9 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoContent.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoContent.kt @@ -19,6 +19,7 @@ import ua.acclorite.book_story.presentation.book_info.BookInfoEvent fun BookInfoContent( book: Book, file: File?, + loadingFile: Boolean, categories: List, bottomSheet: BottomSheet?, dialog: Dialog?, @@ -66,6 +67,7 @@ fun BookInfoContent( bottomSheet = bottomSheet, book = book, file = file, + loadingFile = loadingFile, showPathDialog = showPathDialog, canResetCover = canResetCover, changeCover = changeCover, diff --git a/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoDetailsBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoDetailsBottomSheet.kt index 4e55e637..b3c0db33 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoDetailsBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoDetailsBottomSheet.kt @@ -32,6 +32,7 @@ import java.util.Locale fun BookInfoDetailsBottomSheet( book: Book, file: File?, + loadingFile: Boolean, showPathDialog: (BookInfoEvent.OnShowPathDialog) -> Unit, dismissBottomSheet: (BookInfoEvent.OnDismissBottomSheet) -> Unit ) { @@ -53,6 +54,7 @@ fun BookInfoDetailsBottomSheet( val fileExists = remember(file) { file.let { file -> + if (loadingFile) return@let true if (file == null) return@let false if (file.isDirectory) return@let false if ( @@ -99,7 +101,8 @@ fun BookInfoDetailsBottomSheet( showPathDialog(BookInfoEvent.OnShowPathDialog) }, showError = !fileExists, - errorMessage = stringResource(id = R.string.error_no_file) + errorMessage = stringResource(id = R.string.error_no_file), + loading = loadingFile ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoDetailsBottomSheetItem.kt b/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoDetailsBottomSheetItem.kt index 432e8c0c..813e2c92 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoDetailsBottomSheetItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/book_info/BookInfoDetailsBottomSheetItem.kt @@ -8,6 +8,7 @@ package ua.acclorite.book_story.ui.book_info import androidx.compose.foundation.focusable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row 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.material.icons.Icons import androidx.compose.material.icons.filled.EditNote +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField 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.StyledText import ua.acclorite.book_story.ui.theme.ExpandingTransition +import ua.acclorite.book_story.ui.theme.FadeTransitionPreservingSpace @Composable fun BookInfoDetailsBottomSheetItem( @@ -33,6 +36,7 @@ fun BookInfoDetailsBottomSheetItem( editable: Boolean, showError: Boolean = false, errorMessage: String? = null, + loading: Boolean = false, onEdit: () -> Unit = {} ) { Column( @@ -55,18 +59,23 @@ fun BookInfoDetailsBottomSheetItem( isError = showError, label = { StyledText(label) - } + }, ) - if (editable) { - IconButton( - icon = Icons.Default.EditNote, - contentDescription = R.string.edit_content_desc, - disableOnClick = false, - color = MaterialTheme.colorScheme.primary, - modifier = Modifier.size(24.dp) - ) { - onEdit() + Box(contentAlignment = Alignment.Center) { + FadeTransitionPreservingSpace(visible = loading) { + CircularProgressIndicator(modifier = Modifier.size(24.dp), strokeWidth = 3.2.dp) + } + FadeTransitionPreservingSpace(visible = !loading && editable) { + IconButton( + icon = Icons.Default.EditNote, + contentDescription = R.string.edit_content_desc, + disableOnClick = false, + color = MaterialTheme.colorScheme.primary, + modifier = Modifier.size(24.dp) + ) { + onEdit() + } } } }