| 
					
				 | 
			
			
				@@ -4,9 +4,12 @@ import android.app.Application 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import android.net.Uri 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import android.os.Bundle 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.jakewharton.rxrelay.BehaviorRelay 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import eu.kanade.domain.chapter.interactor.UpdateChapter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import eu.kanade.domain.chapter.model.ChapterUpdate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import eu.kanade.domain.history.interactor.UpsertHistory 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import eu.kanade.domain.history.model.HistoryUpdate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import eu.kanade.tachiyomi.data.cache.CoverCache 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import eu.kanade.tachiyomi.data.database.DatabaseHelper 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import eu.kanade.tachiyomi.data.database.models.History 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import eu.kanade.tachiyomi.data.database.models.Manga 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import eu.kanade.tachiyomi.data.download.DownloadManager 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import eu.kanade.tachiyomi.data.preference.PreferencesHelper 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -62,6 +65,8 @@ class ReaderPresenter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private val coverCache: CoverCache = Injekt.get(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private val preferences: PreferencesHelper = Injekt.get(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private val delayedTrackingStore: DelayedTrackingStore = Injekt.get(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private val upsertHistory: UpsertHistory = Injekt.get(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private val updateChapter: UpdateChapter = Injekt.get(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ) : BasePresenter<ReaderActivity>() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -80,6 +85,11 @@ class ReaderPresenter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private var loader: ChapterLoader? = null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * The time the chapter was started reading 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private var chapterReadStartTime: Long? = null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * Subscription to prevent setting chapters as active from multiple threads. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -168,8 +178,7 @@ class ReaderPresenter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         val currentChapters = viewerChaptersRelay.value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (currentChapters != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             currentChapters.unref() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            saveChapterProgress(currentChapters.currChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            saveChapterHistory(currentChapters.currChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            saveReadingProgress(currentChapters.currChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -200,7 +209,9 @@ class ReaderPresenter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fun onSaveInstanceStateNonConfigurationChange() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         val currentChapter = getCurrentChapter() ?: return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        saveChapterProgress(currentChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        launchIO { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            saveChapterProgress(currentChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -397,7 +408,7 @@ class ReaderPresenter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (selectedChapter != currentChapters.currChapter) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             logcat { "Setting ${selectedChapter.chapter.url} as active" } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            onChapterChanged(currentChapters.currChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            saveReadingProgress(currentChapters.currChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             loadNewChapter(selectedChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -429,43 +440,57 @@ class ReaderPresenter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fun saveCurrentChapterReadingProgress() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        getCurrentChapter()?.let { saveReadingProgress(it) } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * Called when a chapter changed from [fromChapter] to [toChapter]. It updates [fromChapter] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * on the database. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Called when reader chapter is changed in reader or when activity is paused. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private fun onChapterChanged(fromChapter: ReaderChapter) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        saveChapterProgress(fromChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        saveChapterHistory(fromChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private fun saveReadingProgress(readerChapter: ReaderChapter) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        launchIO { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            saveChapterProgress(readerChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            saveChapterHistory(readerChapter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * Saves this [chapter] progress (last read page and whether it's read). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Saves this [readerChapter] progress (last read page and whether it's read). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * If incognito mode isn't on or has at least 1 tracker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private fun saveChapterProgress(chapter: ReaderChapter) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private suspend fun saveChapterProgress(readerChapter: ReaderChapter) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!incognitoMode || hasTrackers) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            db.updateChapterProgress(chapter.chapter).asRxCompletable() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .onErrorComplete() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .subscribeOn(Schedulers.io()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .subscribe() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            val chapter = readerChapter.chapter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            updateChapter.await( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ChapterUpdate( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    id = chapter.id!!, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    read = chapter.read, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    bookmark = chapter.bookmark, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    lastPageRead = chapter.last_page_read.toLong(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * Saves this [chapter] last read history if incognito mode isn't on. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Saves this [readerChapter] last read history if incognito mode isn't on. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private fun saveChapterHistory(chapter: ReaderChapter) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private suspend fun saveChapterHistory(readerChapter: ReaderChapter) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!incognitoMode) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            val history = History.create(chapter.chapter).apply { last_read = Date().time } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            db.upsertHistoryLastRead(history).asRxCompletable() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .onErrorComplete() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .subscribeOn(Schedulers.io()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .subscribe() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            val chapterId = readerChapter.chapter.id!! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            val readAt = Date() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            val sessionReadDuration = chapterReadStartTime?.let { readAt.time - it } ?: 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            upsertHistory.await( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                HistoryUpdate(chapterId, readAt, sessionReadDuration), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ).also { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                chapterReadStartTime = null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    fun saveProgress() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        getCurrentChapter()?.let { onChapterChanged(it) } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fun setReadStartTime() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        chapterReadStartTime = Date().time 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -633,7 +658,7 @@ class ReaderPresenter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * Shares the image of this [page] and notifies the UI with the path of the file to share. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * The image must be first copied to the internal partition because there are many possible 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * formats it can come from, like a zipped chapter, in which case it's not possible to directly 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * get a path to the file and it has to be decompresssed somewhere first. Only the last shared 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * get a path to the file and it has to be decompressed somewhere first. Only the last shared 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * image will be kept so it won't be taking lots of internal disk space. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fun shareImage(page: ReaderPage) { 
			 |