Parcourir la source

Refactor reader progress/history logic

arkon il y a 1 an
Parent
commit
226272f686

+ 9 - 5
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt

@@ -235,13 +235,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)
     }
 
@@ -588,7 +593,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())
@@ -793,7 +798,6 @@ class ReaderActivity : BaseActivity() {
      * Called from the viewer whenever a [page] is marked as active. It updates the values of the
      * bottom menu and delegates the change to the presenter.
      */
-    @SuppressLint("SetTextI18n")
     fun onPageSelected(page: ReaderPage) {
         viewModel.onPageSelected(page)
     }
@@ -811,7 +815,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) }
     }
 
     /**
@@ -898,7 +902,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) {

+ 50 - 61
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt

@@ -57,7 +57,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
@@ -314,12 +313,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) {
@@ -358,7 +360,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
         }
@@ -397,9 +399,7 @@ class ReaderViewModel(
 
     fun onViewerLoaded(viewer: Viewer?) {
         mutableState.update {
-            it.copy(
-                viewer = viewer,
-            )
+            it.copy(viewer = viewer)
         }
     }
 
@@ -414,31 +414,19 @@ class ReaderViewModel(
             return
         }
 
-        val currentChapters = state.value.viewerChapters ?: return
-        val pages = page.chapter.pages ?: return
         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.index + 1,
-            )
-        }
-        if (!incognitoMode) {
-            selectedChapter.chapter.last_page_read = page.index
-            if (selectedChapter.pages?.lastIndex == page.index) {
-                selectedChapter.chapter.read = true
-                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()
@@ -508,42 +496,54 @@ 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
+                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) {
-        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
@@ -552,17 +552,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.
      */