🛠️ Update book's update in BookInfo
* Updated book's text update to match latest app behaviour(chapters)
This commit is contained in:
parent
2334e9c3ec
commit
5eaa3963a7
5 changed files with 204 additions and 138 deletions
|
|
@ -7,41 +7,75 @@ import androidx.compose.runtime.Immutable
|
|||
import androidx.compose.ui.focus.FocusRequester
|
||||
import ua.acclorite.book_story.domain.model.Book
|
||||
import ua.acclorite.book_story.domain.model.Category
|
||||
import ua.acclorite.book_story.domain.model.Chapter
|
||||
import ua.acclorite.book_story.domain.util.OnNavigate
|
||||
import ua.acclorite.book_story.domain.util.UIText
|
||||
|
||||
@Immutable
|
||||
sealed class BookInfoEvent {
|
||||
data object OnShowHideChangeCoverBottomSheet : BookInfoEvent()
|
||||
|
||||
data object OnShowHideDetailsBottomSheet : BookInfoEvent()
|
||||
data class OnDeleteCover(val refreshList: (Book) -> Unit) : BookInfoEvent()
|
||||
data class OnChangeCover(val uri: Uri, val context: Context, val refreshList: (Book) -> Unit) :
|
||||
BookInfoEvent()
|
||||
|
||||
data class OnDeleteCover(
|
||||
val refreshList: (Book) -> Unit
|
||||
) : BookInfoEvent()
|
||||
|
||||
data class OnChangeCover(
|
||||
val uri: Uri,
|
||||
val context: Context,
|
||||
val refreshList: (Book) -> Unit
|
||||
) : BookInfoEvent()
|
||||
|
||||
data object OnCheckCoverReset : BookInfoEvent()
|
||||
|
||||
data class OnResetCoverImage(
|
||||
val refreshList: (Book) -> Unit,
|
||||
val showResult: (UIText) -> Unit
|
||||
) : BookInfoEvent()
|
||||
|
||||
data object OnShowHideEditTitle : BookInfoEvent()
|
||||
data class OnTitleRequestFocus(val focusRequester: FocusRequester) : BookInfoEvent()
|
||||
data class OnTitleValueChange(val value: String) : BookInfoEvent()
|
||||
|
||||
data class OnTitleRequestFocus(
|
||||
val focusRequester: FocusRequester
|
||||
) : BookInfoEvent()
|
||||
|
||||
data class OnTitleValueChange(
|
||||
val value: String
|
||||
) : BookInfoEvent()
|
||||
|
||||
data object OnShowHideEditAuthor : BookInfoEvent()
|
||||
data class OnAuthorRequestFocus(val focusRequester: FocusRequester) : BookInfoEvent()
|
||||
data class OnAuthorValueChange(val value: String) : BookInfoEvent()
|
||||
|
||||
data class OnAuthorRequestFocus(
|
||||
val focusRequester: FocusRequester
|
||||
) : BookInfoEvent()
|
||||
|
||||
data class OnAuthorValueChange(
|
||||
val value: String
|
||||
) : BookInfoEvent()
|
||||
|
||||
data object OnShowHideEditDescription : BookInfoEvent()
|
||||
data class OnDescriptionRequestFocus(val focusRequester: FocusRequester) : BookInfoEvent()
|
||||
data class OnDescriptionValueChange(val value: String) : BookInfoEvent()
|
||||
|
||||
data class OnUpdateData(val refreshList: (Book) -> Unit) : BookInfoEvent()
|
||||
data class OnDescriptionRequestFocus(
|
||||
val focusRequester: FocusRequester
|
||||
) : BookInfoEvent()
|
||||
|
||||
data class OnDescriptionValueChange(
|
||||
val value: String
|
||||
) : BookInfoEvent()
|
||||
|
||||
data class OnUpdateData(
|
||||
val refreshList: (Book) -> Unit
|
||||
) : BookInfoEvent()
|
||||
|
||||
data object OnShowHideDeleteDialog : BookInfoEvent()
|
||||
|
||||
data object OnShowHideMoveDialog : BookInfoEvent()
|
||||
data class OnDeleteBook(val refreshList: () -> Unit, val onNavigate: OnNavigate) :
|
||||
BookInfoEvent()
|
||||
|
||||
data class OnDeleteBook(
|
||||
val refreshList: () -> Unit,
|
||||
val onNavigate: OnNavigate
|
||||
) : BookInfoEvent()
|
||||
|
||||
data class OnMoveBook(
|
||||
val refreshList: (Book) -> Unit,
|
||||
|
|
@ -49,7 +83,10 @@ sealed class BookInfoEvent {
|
|||
val onNavigate: OnNavigate
|
||||
) : BookInfoEvent()
|
||||
|
||||
data class OnSelectCategory(val category: Category) : BookInfoEvent()
|
||||
data class OnSelectCategory(
|
||||
val category: Category
|
||||
) : BookInfoEvent()
|
||||
|
||||
data class OnCopyToClipboard(
|
||||
val context: Context,
|
||||
val text: String,
|
||||
|
|
@ -76,7 +113,8 @@ sealed class BookInfoEvent {
|
|||
data object OnDismissConfirmUpdateDialog : BookInfoEvent()
|
||||
|
||||
data class OnShowConfirmUpdateDialog(
|
||||
val updatedText: List<String>
|
||||
val updatedText: List<String>,
|
||||
val updatedChapters: List<Chapter>
|
||||
) : BookInfoEvent()
|
||||
|
||||
data object OnCancelUpdate : BookInfoEvent()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package ua.acclorite.book_story.presentation.screens.book_info.data
|
|||
import androidx.compose.runtime.Immutable
|
||||
import ua.acclorite.book_story.domain.model.Book
|
||||
import ua.acclorite.book_story.domain.model.Category
|
||||
import ua.acclorite.book_story.domain.model.Chapter
|
||||
import ua.acclorite.book_story.presentation.core.constants.Constants
|
||||
|
||||
@Immutable
|
||||
|
|
@ -11,8 +12,10 @@ data class BookInfoState(
|
|||
|
||||
val isLoadingUpdate: Boolean = false,
|
||||
val isRefreshing: Boolean = false,
|
||||
|
||||
val showConfirmUpdateDialog: Boolean = false,
|
||||
val updatedText: List<String>? = null,
|
||||
val updatedChapters: List<Chapter>? = null,
|
||||
|
||||
val editTitle: Boolean = false,
|
||||
val hasTitleFocused: Boolean = false,
|
||||
|
|
|
|||
|
|
@ -23,24 +23,25 @@ import ua.acclorite.book_story.R
|
|||
import ua.acclorite.book_story.domain.model.BookWithText
|
||||
import ua.acclorite.book_story.domain.model.Category
|
||||
import ua.acclorite.book_story.domain.model.History
|
||||
import ua.acclorite.book_story.domain.model.NullableBook
|
||||
import ua.acclorite.book_story.domain.use_case.CanResetCover
|
||||
import ua.acclorite.book_story.domain.use_case.DeleteBooks
|
||||
import ua.acclorite.book_story.domain.use_case.GetBookById
|
||||
import ua.acclorite.book_story.domain.use_case.GetBookFromFile
|
||||
import ua.acclorite.book_story.domain.use_case.GetText
|
||||
import ua.acclorite.book_story.domain.use_case.InsertHistory
|
||||
import ua.acclorite.book_story.domain.use_case.ParseText
|
||||
import ua.acclorite.book_story.domain.use_case.ResetCoverImage
|
||||
import ua.acclorite.book_story.domain.use_case.UpdateBook
|
||||
import ua.acclorite.book_story.domain.use_case.UpdateBookWithText
|
||||
import ua.acclorite.book_story.domain.use_case.UpdateCoverImageOfBook
|
||||
import ua.acclorite.book_story.domain.util.OnNavigate
|
||||
import ua.acclorite.book_story.domain.util.Resource
|
||||
import ua.acclorite.book_story.domain.util.UIText
|
||||
import ua.acclorite.book_story.presentation.core.navigation.Screen
|
||||
import ua.acclorite.book_story.presentation.core.util.BaseViewModel
|
||||
import java.io.File
|
||||
import java.util.Date
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
@HiltViewModel
|
||||
|
|
@ -50,11 +51,11 @@ class BookInfoViewModel @Inject constructor(
|
|||
private val updateCoverImageOfBook: UpdateCoverImageOfBook,
|
||||
private val insertHistory: InsertHistory,
|
||||
private val deleteBooks: DeleteBooks,
|
||||
private val getBookFromFile: GetBookFromFile,
|
||||
private val getBookById: GetBookById,
|
||||
private val getText: GetText,
|
||||
private val canResetCover: CanResetCover,
|
||||
private val resetCoverImage: ResetCoverImage,
|
||||
private val parseText: ParseText
|
||||
) : BaseViewModel<BookInfoState, BookInfoEvent>() {
|
||||
|
||||
private val _state = MutableStateFlow(BookInfoState())
|
||||
|
|
@ -464,14 +465,14 @@ class BookInfoViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
yield()
|
||||
if (!File(_state.value.book.filePath).exists()) {
|
||||
|
||||
val currentBook = _state.value.book.apply {
|
||||
if (!File(filePath).exists()) {
|
||||
onEvent(
|
||||
BookInfoEvent.OnShowSnackbar(
|
||||
text = event.context.getString(
|
||||
R.string.file_not_found,
|
||||
_state.value.book.filePath
|
||||
.substringAfterLast("/")
|
||||
.takeLast(25)
|
||||
filePath.substringAfterLast("/").takeLast(25)
|
||||
),
|
||||
action = event.context.getString(R.string.retry),
|
||||
onAction = {
|
||||
|
|
@ -486,6 +487,7 @@ class BookInfoViewModel @Inject constructor(
|
|||
snackbarState = event.snackbarState
|
||||
)
|
||||
)
|
||||
|
||||
delay(500)
|
||||
_state.update {
|
||||
it.copy(
|
||||
|
|
@ -494,16 +496,15 @@ class BookInfoViewModel @Inject constructor(
|
|||
}
|
||||
return@launch
|
||||
}
|
||||
|
||||
yield()
|
||||
val updatedBook = getBookFromFile.execute(File(_state.value.book.filePath))
|
||||
yield()
|
||||
|
||||
if (updatedBook is NullableBook.Null) {
|
||||
}
|
||||
val updatedBook = parseText.execute(File(currentBook.filePath)).apply {
|
||||
if (this is Resource.Error || data == null) {
|
||||
onEvent(
|
||||
BookInfoEvent.OnShowSnackbar(
|
||||
text = updatedBook.message?.asString(event.context)
|
||||
?: event.context.getString(R.string.error_something_went_wrong_with_file),
|
||||
text = message?.asString(event.context)
|
||||
?: event.context.getString(
|
||||
R.string.error_something_went_wrong_with_file
|
||||
),
|
||||
action = event.context.getString(R.string.retry),
|
||||
onAction = {
|
||||
onEvent(
|
||||
|
|
@ -526,21 +527,22 @@ class BookInfoViewModel @Inject constructor(
|
|||
}
|
||||
return@launch
|
||||
}
|
||||
}.data!!
|
||||
|
||||
yield()
|
||||
|
||||
val book = _state.value.book
|
||||
val updatedText = updatedBook.map { it.text }.flatten()
|
||||
val text = getText.execute(currentBook.textPath)
|
||||
|
||||
var textUpdated = false
|
||||
|
||||
val updatedText = updatedBook.bookWithTextAndCover!!.text
|
||||
val text = getText.execute(book.textPath)
|
||||
|
||||
if (updatedText != text) {
|
||||
textUpdated = true
|
||||
val updatedChapters = updatedBook.map { it.chapter }.run {
|
||||
if (size < 2) return@run emptyList()
|
||||
return@run this
|
||||
}
|
||||
val chapters = currentBook.chapters
|
||||
|
||||
yield()
|
||||
if (!textUpdated) {
|
||||
|
||||
if (updatedText == text && updatedChapters == chapters) {
|
||||
onEvent(
|
||||
BookInfoEvent.OnShowSnackbar(
|
||||
event.context.getString(R.string.nothing_changed),
|
||||
|
|
@ -559,9 +561,11 @@ class BookInfoViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
yield()
|
||||
|
||||
onEvent(
|
||||
BookInfoEvent.OnShowConfirmUpdateDialog(
|
||||
updatedText = updatedBook.bookWithTextAndCover.text,
|
||||
updatedText = updatedText,
|
||||
updatedChapters = updatedChapters
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -577,7 +581,8 @@ class BookInfoViewModel @Inject constructor(
|
|||
_state.update {
|
||||
it.copy(
|
||||
showConfirmUpdateDialog = false,
|
||||
updatedText = null
|
||||
updatedText = null,
|
||||
updatedChapters = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -586,7 +591,8 @@ class BookInfoViewModel @Inject constructor(
|
|||
_state.update {
|
||||
it.copy(
|
||||
showConfirmUpdateDialog = true,
|
||||
updatedText = event.updatedText
|
||||
updatedText = event.updatedText,
|
||||
updatedChapters = event.updatedChapters
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -600,7 +606,7 @@ class BookInfoViewModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
if (_state.value.updatedText == null) {
|
||||
if (_state.value.updatedText == null || _state.value.updatedChapters == null) {
|
||||
onEvent(
|
||||
BookInfoEvent.OnShowSnackbar(
|
||||
text = event.context.getString(
|
||||
|
|
@ -619,24 +625,33 @@ class BookInfoViewModel @Inject constructor(
|
|||
snackbarState = event.snackbarState
|
||||
)
|
||||
)
|
||||
|
||||
delay(500)
|
||||
_state.update {
|
||||
it.copy(
|
||||
isRefreshing = false
|
||||
isRefreshing = false,
|
||||
updatedText = null,
|
||||
updatedChapters = null
|
||||
)
|
||||
}
|
||||
return@launch
|
||||
}
|
||||
|
||||
val updatedText = _state.value.updatedText ?: return@launch
|
||||
val isSuccess = updateBookWithText.execute(
|
||||
val updatedChapters = _state.value.updatedChapters ?: return@launch
|
||||
|
||||
updateBookWithText.execute(
|
||||
BookWithText(
|
||||
book = _state.value.book,
|
||||
book = _state.value.book.copy(
|
||||
scrollIndex = (updatedText.size * _state.value.book.progress).roundToInt(),
|
||||
scrollOffset = 0,
|
||||
chapters = updatedChapters
|
||||
),
|
||||
text = updatedText
|
||||
)
|
||||
)
|
||||
).apply {
|
||||
if (this) return@apply
|
||||
|
||||
if (!isSuccess) {
|
||||
onEvent(
|
||||
BookInfoEvent.OnShowSnackbar(
|
||||
text = event.context.getString(
|
||||
|
|
@ -655,17 +670,20 @@ class BookInfoViewModel @Inject constructor(
|
|||
snackbarState = event.snackbarState
|
||||
)
|
||||
)
|
||||
|
||||
delay(500)
|
||||
_state.update {
|
||||
it.copy(
|
||||
isRefreshing = false
|
||||
isRefreshing = false,
|
||||
updatedText = null,
|
||||
updatedChapters = null
|
||||
)
|
||||
}
|
||||
return@launch
|
||||
}
|
||||
|
||||
val newBook = getBookById.execute(_state.value.book.id)
|
||||
if (newBook == null) {
|
||||
getBookById.execute(_state.value.book.id).apply {
|
||||
if (this == null) {
|
||||
onEvent(
|
||||
BookInfoEvent.OnShowSnackbar(
|
||||
text = event.context.getString(
|
||||
|
|
@ -684,10 +702,13 @@ class BookInfoViewModel @Inject constructor(
|
|||
snackbarState = event.snackbarState
|
||||
)
|
||||
)
|
||||
|
||||
delay(500)
|
||||
_state.update {
|
||||
it.copy(
|
||||
isRefreshing = false
|
||||
isRefreshing = false,
|
||||
updatedText = null,
|
||||
updatedChapters = null
|
||||
)
|
||||
}
|
||||
return@launch
|
||||
|
|
@ -695,8 +716,9 @@ class BookInfoViewModel @Inject constructor(
|
|||
|
||||
_state.update {
|
||||
it.copy(
|
||||
book = newBook,
|
||||
updatedText = null
|
||||
book = this,
|
||||
updatedText = null,
|
||||
updatedChapters = null
|
||||
)
|
||||
}
|
||||
event.refreshList(_state.value.book)
|
||||
|
|
@ -718,6 +740,7 @@ class BookInfoViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is BookInfoEvent.OnCancelUpdate -> {
|
||||
_state.update {
|
||||
|
|
@ -725,7 +748,9 @@ class BookInfoViewModel @Inject constructor(
|
|||
|
||||
it.copy(
|
||||
showConfirmUpdateDialog = false,
|
||||
isLoadingUpdate = false
|
||||
isLoadingUpdate = false,
|
||||
updatedText = null,
|
||||
updatedChapters = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@
|
|||
Після видалення всієї історії порядок книг буде скинутий.
|
||||
</string>
|
||||
<string name="confirm_update_description">
|
||||
При підтвердженні текст цієї книги буде оновлений.
|
||||
Будь ласка, запам\'ятайте де ви зупинилися перед оновленням тексту.
|
||||
Оновіть текст та розділи цієї книги.
|
||||
Прогрес повинен залишитися незмінним, якщо порядок параграфів не був змінений.
|
||||
</string>
|
||||
<string name="update_app_description">
|
||||
Нова версія Book\'s Story була знайдена.
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@
|
|||
After deleting the whole history, the order of the books will be reset.
|
||||
</string>
|
||||
<string name="confirm_update_description">
|
||||
By confirming this book\'s text will be updated.
|
||||
Please remember where you left before updating text.
|
||||
Update this book\'s text and chapters.
|
||||
The progress should remain unchanged unless order of paragraphs was changed.
|
||||
</string>
|
||||
<string name="update_app_description">
|
||||
New version of Book\'s Story was found.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue