diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index 51c6fcf0e..482ad264d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -296,13 +296,18 @@ class ReaderActivity : BaseActivity() { readingModeToast?.cancel() } + override fun onPause() { + viewModel.flushReadTimer() + super.onPause() + } + /** * Set menu visibility again on activity resume to apply immersive mode again if needed. * Helps with rotations. */ override fun onResume() { super.onResume() - viewModel.setReadStartTime() + viewModel.restartReadTimer() setMenuVisibility(viewModel.state.value.menuVisible, animate = false) } @@ -1005,7 +1010,7 @@ class ReaderActivity : BaseActivity() { * Sets the visibility of the menu according to [visible] and with an optional parameter to * [animate] the views. */ - fun setMenuVisibility(visible: Boolean, animate: Boolean = true) { + private fun setMenuVisibility(visible: Boolean, animate: Boolean = true) { viewModel.showMenus(visible) if (visible) { windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) @@ -1301,13 +1306,13 @@ class ReaderActivity : BaseActivity() { @SuppressLint("SetTextI18n") fun onPageSelected(page: ReaderPage, hasExtraPage: Boolean = false) { // SY --> - val currentPage = if (hasExtraPage) { + val currentPageText = if (hasExtraPage) { val invertDoublePage = (viewModel.state.value.viewer as? PagerViewer)?.config?.invertDoublePages ?: false if (resources.isLTR xor invertDoublePage) "${page.number}-${page.number + 1}" else "${page.number + 1}-${page.number}" } else { "${page.number}" } - viewModel.onPageSelected(page, hasExtraPage, currentPage) + viewModel.onPageSelected(page, currentPageText) // SY <-- } @@ -1326,7 +1331,7 @@ class ReaderActivity : BaseActivity() { * the viewer is reaching the beginning or end of a chapter or the transition page is active. */ fun requestPreloadChapter(chapter: ReaderChapter) { - lifecycleScope.launchIO { viewModel.preloadChapter(chapter) } + lifecycleScope.launchIO { viewModel.preload(chapter) } } /** @@ -1421,7 +1426,7 @@ class ReaderActivity : BaseActivity() { /** * Updates viewer inset depending on fullscreen reader preferences. */ - fun updateViewerInset(fullscreen: Boolean) { + private fun updateViewerInset(fullscreen: Boolean) { viewModel.state.value.viewer?.getView()?.applyInsetter { if (!fullscreen) { type(navigationBars = true, statusBars = true) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt index 032c0d624..49491ee88 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt @@ -75,7 +75,6 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import logcat.LogPriority import tachiyomi.core.util.lang.launchIO @@ -410,12 +409,15 @@ class ReaderViewModel( * Called when the user changed to the given [chapter] when changing pages from the viewer. * It's used only to set this chapter as active. */ - private suspend fun loadNewChapter(chapter: ReaderChapter) { + private fun loadNewChapter(chapter: ReaderChapter) { val loader = loader ?: return - logcat { "Loading ${chapter.chapter.url}" } + viewModelScope.launchIO { + logcat { "Loading ${chapter.chapter.url}" } + + flushReadTimer() + restartReadTimer() - withIOContext { try { loadChapter(loader, chapter) } catch (e: Throwable) { @@ -459,7 +461,7 @@ class ReaderViewModel( * Called when the viewers decide it's a good time to preload a [chapter] and improve the UX so * that the user doesn't have to wait too long to continue reading. */ - private suspend fun preload(chapter: ReaderChapter) { + suspend fun preload(chapter: ReaderChapter) { if (chapter.state is ReaderChapter.State.Loaded || chapter.state == ReaderChapter.State.Loading) { return } @@ -498,9 +500,7 @@ class ReaderViewModel( fun onViewerLoaded(viewer: Viewer?) { mutableState.update { - it.copy( - viewer = viewer, - ) + it.copy(viewer = viewer) } } @@ -509,53 +509,29 @@ class ReaderViewModel( * read, update tracking services, enqueue downloaded chapter deletion, and updating the active chapter if this * [page]'s chapter is different from the currently active. */ - fun onPageSelected(page: ReaderPage, hasExtraPage: Boolean, currentPage: String) { + fun onPageSelected(page: ReaderPage, currentPageText: String) { // InsertPage and StencilPage doesn't change page progress if (page is InsertPage || page is StencilPage) { return } - val currentChapters = state.value.viewerChapters ?: return - val pages = page.chapter.pages ?: return + // SY --> + mutableState.update { it.copy(currentPageText = currentPageText) } + // SY <-- + val selectedChapter = page.chapter + val pages = selectedChapter.pages ?: return // Save last page read and mark as read if needed - saveReadingProgress() - mutableState.update { - it.copy( - currentPage = page.number, - // SY --> - currentPageText = currentPage, - // SY <-- - ) - } - selectedChapter.chapter.last_page_read = page.index - if ( - (selectedChapter.pages?.lastIndex == page.index && !incognitoMode) || - (hasExtraPage && selectedChapter.pages?.lastIndex?.minus(1) == page.index && !incognitoMode) - ) { - selectedChapter.chapter.read = true - // SY --> - if (manga?.isEhBasedManga() == true) { - viewModelScope.launchNonCancellable { - chapterList - .filter { it.chapter.source_order > selectedChapter.chapter.source_order } - .onEach { - it.chapter.read = true - saveChapterProgress(it) - } - } - } - // SY <-- - updateTrackChapterRead(selectedChapter) - deleteChapterIfNeeded(selectedChapter) + viewModelScope.launchNonCancellable { + updateChapterProgress(page.index) } - if (selectedChapter != currentChapters.currChapter) { + if (selectedChapter != getCurrentChapter()) { logcat { "Setting ${selectedChapter.chapter.url} as active" } - setReadStartTime() - viewModelScope.launch { loadNewChapter(selectedChapter) } + loadNewChapter(selectedChapter) } + val inDownloadRange = page.number.toDouble() / pages.size > 0.25 if (inDownloadRange) { downloadNextChapters() @@ -627,45 +603,69 @@ class ReaderViewModel( } /** - * Called when reader chapter is changed in reader or when activity is paused. + * Saves the chapter progress (last read page and whether it's read) + * if incognito mode isn't on. */ - private fun saveReadingProgress() { - getCurrentChapter()?.let { - viewModelScope.launchNonCancellable { - saveChapterProgress(it) - saveChapterHistory(it) + private suspend fun updateChapterProgress(pageIndex: Int) { + val readerChapter = getCurrentChapter() ?: return + + mutableState.update { + it.copy(currentPage = pageIndex + 1) + } + + if (!incognitoMode) { + readerChapter.requestedPage = pageIndex + readerChapter.chapter.last_page_read = pageIndex + + updateChapter.await( + ChapterUpdate( + id = readerChapter.chapter.id!!, + read = readerChapter.chapter.read, + bookmark = readerChapter.chapter.bookmark, + lastPageRead = readerChapter.chapter.last_page_read.toLong(), + ), + ) + + if (readerChapter.pages?.lastIndex == pageIndex) { + readerChapter.chapter.read = true + // SY --> + if (manga?.isEhBasedManga() == true) { + viewModelScope.launchNonCancellable { + val chapterUpdates = chapterList + .filter { it.chapter.source_order > readerChapter.chapter.source_order } + .map { chapter -> + ChapterUpdate( + id = chapter.chapter.id!!, + read = true, + ) + } + updateChapter.awaitAll(chapterUpdates) + } + } + // SY <-- + updateTrackChapterRead(readerChapter) + deleteChapterIfNeeded(readerChapter) } } } - /** - * Saves this [readerChapter] progress (last read page and whether it's read) - * if incognito mode isn't on. - */ - private suspend fun saveChapterProgress(readerChapter: ReaderChapter) { - // SY --> - readerChapter.requestedPage = readerChapter.chapter.last_page_read - // SY <-- - if (incognitoMode) return + fun restartReadTimer() { + chapterReadStartTime = Date().time + } - val chapter = readerChapter.chapter - readerChapter.requestedPage = chapter.last_page_read - updateChapter.await( - ChapterUpdate( - id = chapter.id!!, - read = chapter.read, - bookmark = chapter.bookmark, - lastPageRead = chapter.last_page_read.toLong(), - ), - ) + fun flushReadTimer() { + viewModelScope.launchNonCancellable { + updateHistory() + } } /** - * Saves this [readerChapter] last read history if incognito mode isn't on. + * Saves the chapter last read history if incognito mode isn't on. */ - private suspend fun saveChapterHistory(readerChapter: ReaderChapter) { + private suspend fun updateHistory() { if (incognitoMode) return + val readerChapter = getCurrentChapter() ?: return val chapterId = readerChapter.chapter.id!! val endTime = Date() val sessionReadDuration = chapterReadStartTime?.let { endTime.time - it } ?: 0 @@ -674,17 +674,6 @@ class ReaderViewModel( chapterReadStartTime = null } - fun setReadStartTime() { - chapterReadStartTime = Date().time - } - - /** - * Called from the activity to preload the given [chapter]. - */ - suspend fun preloadChapter(chapter: ReaderChapter) { - preload(chapter) - } - /** * Called from the activity to load and set the next chapter as active. */