From 7690cafec5de728604879b840df9142a1a02ff43 Mon Sep 17 00:00:00 2001 From: Acclorite <140836141+Acclorite@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:06:11 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Improve=20progress=20display=20i?= =?UTF-8?q?n=20Reader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Book and chapter (in "($cp)") progress * Sync chapter & book progress calculation Resolves: #103 --- .../screens/reader/ReaderScreen.kt | 1 - .../components/app_bar/ReaderBottomBar.kt | 16 +++- .../screens/reader/data/ReaderViewModel.kt | 85 ++++++++----------- 3 files changed, 50 insertions(+), 52 deletions(-) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt index 4e1173fe..4f1bba92 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt @@ -168,7 +168,6 @@ fun ReaderScreenRoot(screen: Screen.Reader) { onLibraryEvent(LibraryEvent.OnUpdateBook(it)) onHistoryEvent(HistoryEvent.OnUpdateBook(it)) } - viewModel.onUpdateCurrentChapter() } DisposableEffect(mainState.value.screenOrientation) { context.requestedOrientation = mainState.value.screenOrientation.code diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt index ed826e1e..bd0bdf81 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt @@ -53,11 +53,23 @@ fun ReaderBottomBar() { val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onHistoryEvent = LocalHistoryViewModel.current.onEvent - val progress by remember { + val bookProgress by remember { derivedStateOf { - "${state.value.book.progress.calculateProgress(4)}%" + "${state.value.book.progress.calculateProgress(2)}%" } } + val chapterProgress by remember { + derivedStateOf { + if (state.value.currentChapter == null) return@derivedStateOf "" + " (${state.value.currentChapterProgress.calculateProgress(2)}%)" + } + } + val progress by remember { + derivedStateOf { + "$bookProgress$chapterProgress" + } + } + val arrowDirection by remember { derivedStateOf { val checkpoint = state.value.checkpoint.first diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt index 6a36c12c..f1079360 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt @@ -26,6 +26,7 @@ import kotlinx.coroutines.withContext import kotlinx.coroutines.yield import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.Book +import ua.acclorite.book_story.domain.model.Chapter import ua.acclorite.book_story.domain.use_case.book.CheckForTextUpdate import ua.acclorite.book_story.domain.use_case.book.GetBookById import ua.acclorite.book_story.domain.use_case.book.GetText @@ -96,10 +97,13 @@ class ReaderViewModel @Inject constructor( }.collectLatest { itemsCount -> if (itemsCount < _state.value.text.size) return@collectLatest - _state.value.listState.requestScrollToItem( - _state.value.book.scrollIndex, - _state.value.book.scrollOffset - ) + _state.value.book.apply { + _state.value.listState.requestScrollToItem( + scrollIndex, + scrollOffset + ) + updateChapter(index = scrollIndex) + } event.checkForUpdate() @@ -564,53 +568,41 @@ class ReaderViewModel @Inject constructor( fun onUpdateProgress(refreshList: (Book) -> Unit) { viewModelScope.launch(Dispatchers.Main) { snapshotFlow { - _state.value.listState.firstVisibleItemIndex to _state.value.listState.firstVisibleItemScrollOffset - } - .distinctUntilChanged() - .debounce(300) - .collectLatest { (firstVisibleItemIndex, firstVisibleItemOffset) -> - calculateProgress(firstVisibleItemIndex).apply { - if (this == _state.value.book.progress) return@apply + _state.value.listState.run { firstVisibleItemIndex to firstVisibleItemScrollOffset } + }.distinctUntilChanged().debounce(300).collectLatest { (index, offset) -> + val progress = calculateProgress(index) + if (progress == _state.value.book.progress) return@collectLatest + val (currentChapter, currentChapterProgress) = calculateCurrentChapter(index) - onEvent( - ReaderEvent.OnChangeProgress( - progress = this, - firstVisibleItemIndex = firstVisibleItemIndex, - firstVisibleItemOffset = firstVisibleItemOffset, - refreshList = { book -> - refreshList(book) - } - ) - ) - } + _state.update { + it.copy( + book = it.book.copy( + progress = progress, + scrollIndex = index, + scrollOffset = offset + ), + currentChapter = currentChapter, + currentChapterProgress = currentChapterProgress + ) } - } - } - @OptIn(FlowPreview::class) - fun onUpdateCurrentChapter() { - viewModelScope.launch(Dispatchers.Main) { - snapshotFlow { - _state.value.listState.firstVisibleItemIndex + updateBook.execute(_state.value.book) + refreshList(_state.value.book) } - .distinctUntilChanged() - .debounce(300) - .collectLatest { index -> - if (_state.value.book.chapters.isEmpty()) { - _state.update { - it.copy( - currentChapter = null - ) - } - return@collectLatest - } - - updateChapter(index) - } } } private fun updateChapter(index: Int) { + val (currentChapter, currentChapterProgress) = calculateCurrentChapter(index) + _state.update { + it.copy( + currentChapter = currentChapter, + currentChapterProgress = currentChapterProgress + ) + } + } + + private fun calculateCurrentChapter(index: Int): Pair { val currentChapter = _state.value.book.chapters.find { chapter -> index in chapter.startIndex..chapter.endIndex } @@ -622,12 +614,7 @@ class ReaderViewModel @Inject constructor( (currentIndex / endIndex.toFloat()) }.coerceAndPreventNaN() - _state.update { - it.copy( - currentChapter = currentChapter, - currentChapterProgress = currentChapterProgress - ) - } + return currentChapter to currentChapterProgress } private fun calculateProgress(firstVisibleItemIndex: Int? = null): Float {