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