mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Reader: Save reading progress with SQLDelight (#7185)
* Use SQLDelight in reader to update history * Move chapter progress to sqldelight * Review Changes Co-Authored-By: inorichi <len@kanade.eu> * Review Changes 2 Co-authored-by: FourTOne5 <59261191+FourTOne5@users.noreply.github.com> Co-authored-by: inorichi <len@kanade.eu>
This commit is contained in:
		
							
								
								
									
										3
									
								
								app/src/main/java/eu/kanade/data/DatabaseUtils.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/src/main/java/eu/kanade/data/DatabaseUtils.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
package eu.kanade.data
 | 
			
		||||
 | 
			
		||||
fun Boolean.toLong() = if (this) 1L else 0L
 | 
			
		||||
@@ -0,0 +1,36 @@
 | 
			
		||||
package eu.kanade.data.chapter
 | 
			
		||||
 | 
			
		||||
import eu.kanade.data.DatabaseHandler
 | 
			
		||||
import eu.kanade.data.toLong
 | 
			
		||||
import eu.kanade.domain.chapter.model.ChapterUpdate
 | 
			
		||||
import eu.kanade.domain.chapter.repository.ChapterRepository
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.logcat
 | 
			
		||||
import logcat.LogPriority
 | 
			
		||||
 | 
			
		||||
class ChapterRepositoryImpl(
 | 
			
		||||
    private val databaseHandler: DatabaseHandler,
 | 
			
		||||
) : ChapterRepository {
 | 
			
		||||
 | 
			
		||||
    override suspend fun update(chapterUpdate: ChapterUpdate) {
 | 
			
		||||
        try {
 | 
			
		||||
            databaseHandler.await {
 | 
			
		||||
                chaptersQueries.update(
 | 
			
		||||
                    chapterUpdate.mangaId,
 | 
			
		||||
                    chapterUpdate.url,
 | 
			
		||||
                    chapterUpdate.name,
 | 
			
		||||
                    chapterUpdate.scanlator,
 | 
			
		||||
                    chapterUpdate.read?.toLong(),
 | 
			
		||||
                    chapterUpdate.bookmark?.toLong(),
 | 
			
		||||
                    chapterUpdate.lastPageRead,
 | 
			
		||||
                    chapterUpdate.chapterNumber?.toDouble(),
 | 
			
		||||
                    chapterUpdate.sourceOrder,
 | 
			
		||||
                    chapterUpdate.dateFetch,
 | 
			
		||||
                    chapterUpdate.dateUpload,
 | 
			
		||||
                    chapterId = chapterUpdate.id,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            logcat(LogPriority.ERROR, e)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -4,16 +4,17 @@ import eu.kanade.domain.history.model.History
 | 
			
		||||
import eu.kanade.domain.history.model.HistoryWithRelations
 | 
			
		||||
import java.util.Date
 | 
			
		||||
 | 
			
		||||
val historyMapper: (Long, Long, Date?, Date?) -> History = { id, chapterId, readAt, _ ->
 | 
			
		||||
val historyMapper: (Long, Long, Date?, Long) -> History = { id, chapterId, readAt, readDuration ->
 | 
			
		||||
    History(
 | 
			
		||||
        id = id,
 | 
			
		||||
        chapterId = chapterId,
 | 
			
		||||
        readAt = readAt,
 | 
			
		||||
        readDuration = readDuration,
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val historyWithRelationsMapper: (Long, Long, Long, String, String?, Float, Date?) -> HistoryWithRelations = {
 | 
			
		||||
        historyId, mangaId, chapterId, title, thumbnailUrl, chapterNumber, readAt ->
 | 
			
		||||
val historyWithRelationsMapper: (Long, Long, Long, String, String?, Float, Date?, Long) -> HistoryWithRelations = {
 | 
			
		||||
        historyId, mangaId, chapterId, title, thumbnailUrl, chapterNumber, readAt, readDuration ->
 | 
			
		||||
    HistoryWithRelations(
 | 
			
		||||
        id = historyId,
 | 
			
		||||
        chapterId = chapterId,
 | 
			
		||||
@@ -22,5 +23,6 @@ val historyWithRelationsMapper: (Long, Long, Long, String, String?, Float, Date?
 | 
			
		||||
        thumbnailUrl = thumbnailUrl ?: "",
 | 
			
		||||
        chapterNumber = chapterNumber,
 | 
			
		||||
        readAt = readAt,
 | 
			
		||||
        readDuration = readDuration,
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import eu.kanade.data.DatabaseHandler
 | 
			
		||||
import eu.kanade.data.chapter.chapterMapper
 | 
			
		||||
import eu.kanade.data.manga.mangaMapper
 | 
			
		||||
import eu.kanade.domain.chapter.model.Chapter
 | 
			
		||||
import eu.kanade.domain.history.model.HistoryUpdate
 | 
			
		||||
import eu.kanade.domain.history.model.HistoryWithRelations
 | 
			
		||||
import eu.kanade.domain.history.repository.HistoryRepository
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
@@ -89,4 +90,28 @@ class HistoryRepositoryImpl(
 | 
			
		||||
            false
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun upsertHistory(historyUpdate: HistoryUpdate) {
 | 
			
		||||
        try {
 | 
			
		||||
            try {
 | 
			
		||||
                handler.await {
 | 
			
		||||
                    historyQueries.insert(
 | 
			
		||||
                        historyUpdate.chapterId,
 | 
			
		||||
                        historyUpdate.readAt,
 | 
			
		||||
                        historyUpdate.sessionReadDuration,
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            } catch (e: Exception) {
 | 
			
		||||
                handler.await {
 | 
			
		||||
                    historyQueries.update(
 | 
			
		||||
                        historyUpdate.readAt,
 | 
			
		||||
                        historyUpdate.sessionReadDuration,
 | 
			
		||||
                        historyUpdate.chapterId,
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            logcat(LogPriority.ERROR, throwable = e)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,11 @@
 | 
			
		||||
package eu.kanade.domain
 | 
			
		||||
 | 
			
		||||
import eu.kanade.data.chapter.ChapterRepositoryImpl
 | 
			
		||||
import eu.kanade.data.history.HistoryRepositoryImpl
 | 
			
		||||
import eu.kanade.data.manga.MangaRepositoryImpl
 | 
			
		||||
import eu.kanade.data.source.SourceRepositoryImpl
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.UpdateChapter
 | 
			
		||||
import eu.kanade.domain.chapter.repository.ChapterRepository
 | 
			
		||||
import eu.kanade.domain.extension.interactor.GetExtensionLanguages
 | 
			
		||||
import eu.kanade.domain.extension.interactor.GetExtensionSources
 | 
			
		||||
import eu.kanade.domain.extension.interactor.GetExtensionUpdates
 | 
			
		||||
@@ -12,6 +15,7 @@ import eu.kanade.domain.history.interactor.GetHistory
 | 
			
		||||
import eu.kanade.domain.history.interactor.GetNextChapterForManga
 | 
			
		||||
import eu.kanade.domain.history.interactor.RemoveHistoryById
 | 
			
		||||
import eu.kanade.domain.history.interactor.RemoveHistoryByMangaId
 | 
			
		||||
import eu.kanade.domain.history.interactor.UpsertHistory
 | 
			
		||||
import eu.kanade.domain.history.repository.HistoryRepository
 | 
			
		||||
import eu.kanade.domain.manga.interactor.GetFavoritesBySourceId
 | 
			
		||||
import eu.kanade.domain.manga.interactor.ResetViewerFlags
 | 
			
		||||
@@ -38,9 +42,13 @@ class DomainModule : InjektModule {
 | 
			
		||||
        addFactory { GetNextChapterForManga(get()) }
 | 
			
		||||
        addFactory { ResetViewerFlags(get()) }
 | 
			
		||||
 | 
			
		||||
        addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
 | 
			
		||||
        addFactory { UpdateChapter(get()) }
 | 
			
		||||
 | 
			
		||||
        addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
 | 
			
		||||
        addFactory { DeleteHistoryTable(get()) }
 | 
			
		||||
        addFactory { GetHistory(get()) }
 | 
			
		||||
        addFactory { UpsertHistory(get()) }
 | 
			
		||||
        addFactory { RemoveHistoryById(get()) }
 | 
			
		||||
        addFactory { RemoveHistoryByMangaId(get()) }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,13 @@
 | 
			
		||||
package eu.kanade.domain.chapter.interactor
 | 
			
		||||
 | 
			
		||||
import eu.kanade.domain.chapter.model.ChapterUpdate
 | 
			
		||||
import eu.kanade.domain.chapter.repository.ChapterRepository
 | 
			
		||||
 | 
			
		||||
class UpdateChapter(
 | 
			
		||||
    private val chapterRepository: ChapterRepository,
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    suspend fun await(chapterUpdate: ChapterUpdate) {
 | 
			
		||||
        chapterRepository.update(chapterUpdate)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
package eu.kanade.domain.chapter.model
 | 
			
		||||
 | 
			
		||||
data class ChapterUpdate(
 | 
			
		||||
    val id: Long,
 | 
			
		||||
    val mangaId: Long? = null,
 | 
			
		||||
    val read: Boolean? = null,
 | 
			
		||||
    val bookmark: Boolean? = null,
 | 
			
		||||
    val lastPageRead: Long? = null,
 | 
			
		||||
    val dateFetch: Long? = null,
 | 
			
		||||
    val sourceOrder: Long? = null,
 | 
			
		||||
    val url: String? = null,
 | 
			
		||||
    val name: String? = null,
 | 
			
		||||
    val dateUpload: Long? = null,
 | 
			
		||||
    val chapterNumber: Float? = null,
 | 
			
		||||
    val scanlator: String? = null,
 | 
			
		||||
)
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
package eu.kanade.domain.chapter.repository
 | 
			
		||||
 | 
			
		||||
import eu.kanade.domain.chapter.model.ChapterUpdate
 | 
			
		||||
 | 
			
		||||
interface ChapterRepository {
 | 
			
		||||
 | 
			
		||||
    suspend fun update(chapterUpdate: ChapterUpdate)
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,13 @@
 | 
			
		||||
package eu.kanade.domain.history.interactor
 | 
			
		||||
 | 
			
		||||
import eu.kanade.domain.history.model.HistoryUpdate
 | 
			
		||||
import eu.kanade.domain.history.repository.HistoryRepository
 | 
			
		||||
 | 
			
		||||
class UpsertHistory(
 | 
			
		||||
    private val historyRepository: HistoryRepository,
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    suspend fun await(historyUpdate: HistoryUpdate) {
 | 
			
		||||
        historyRepository.upsertHistory(historyUpdate)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,8 @@ package eu.kanade.domain.history.model
 | 
			
		||||
import java.util.Date
 | 
			
		||||
 | 
			
		||||
data class History(
 | 
			
		||||
    val id: Long?,
 | 
			
		||||
    val id: Long,
 | 
			
		||||
    val chapterId: Long,
 | 
			
		||||
    val readAt: Date?,
 | 
			
		||||
    val readDuration: Long,
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
package eu.kanade.domain.history.model
 | 
			
		||||
 | 
			
		||||
import java.util.Date
 | 
			
		||||
 | 
			
		||||
data class HistoryUpdate(
 | 
			
		||||
    val chapterId: Long,
 | 
			
		||||
    val readAt: Date,
 | 
			
		||||
    val sessionReadDuration: Long,
 | 
			
		||||
)
 | 
			
		||||
@@ -10,4 +10,5 @@ data class HistoryWithRelations(
 | 
			
		||||
    val thumbnailUrl: String,
 | 
			
		||||
    val chapterNumber: Float,
 | 
			
		||||
    val readAt: Date?,
 | 
			
		||||
    val readDuration: Long,
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package eu.kanade.domain.history.repository
 | 
			
		||||
 | 
			
		||||
import androidx.paging.PagingSource
 | 
			
		||||
import eu.kanade.domain.chapter.model.Chapter
 | 
			
		||||
import eu.kanade.domain.history.model.HistoryUpdate
 | 
			
		||||
import eu.kanade.domain.history.model.HistoryWithRelations
 | 
			
		||||
 | 
			
		||||
interface HistoryRepository {
 | 
			
		||||
@@ -15,4 +16,6 @@ interface HistoryRepository {
 | 
			
		||||
    suspend fun resetHistoryByMangaId(mangaId: Long)
 | 
			
		||||
 | 
			
		||||
    suspend fun deleteAllHistory(): Boolean
 | 
			
		||||
 | 
			
		||||
    suspend fun upsertHistory(historyUpdate: HistoryUpdate)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -55,8 +55,7 @@ class AppModule(val app: Application) : InjektModule {
 | 
			
		||||
            Database(
 | 
			
		||||
                driver = get(),
 | 
			
		||||
                historyAdapter = History.Adapter(
 | 
			
		||||
                    history_last_readAdapter = dateAdapter,
 | 
			
		||||
                    history_time_readAdapter = dateAdapter,
 | 
			
		||||
                    last_readAdapter = dateAdapter,
 | 
			
		||||
                ),
 | 
			
		||||
                mangasAdapter = Mangas.Adapter(
 | 
			
		||||
                    genreAdapter = listOfStringsAdapter,
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ interface History : Serializable {
 | 
			
		||||
    var last_read: Long
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Total time chapter was read - todo not yet implemented
 | 
			
		||||
     * Total time chapter was read
 | 
			
		||||
     */
 | 
			
		||||
    var time_read: Long
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ class HistoryImpl : History {
 | 
			
		||||
    override var last_read: Long = 0
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Total time chapter was read - todo not yet implemented
 | 
			
		||||
     * Total time chapter was read
 | 
			
		||||
     */
 | 
			
		||||
    override var time_read: Long = 0
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -232,7 +232,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onPause() {
 | 
			
		||||
        presenter.saveProgress()
 | 
			
		||||
        presenter.saveCurrentChapterReadingProgress()
 | 
			
		||||
        super.onPause()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -242,6 +242,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
 | 
			
		||||
     */
 | 
			
		||||
    override fun onResume() {
 | 
			
		||||
        super.onResume()
 | 
			
		||||
        presenter.setReadStartTime()
 | 
			
		||||
        setMenuVisibility(menuVisible, animate = false)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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(
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when a chapter changed from [fromChapter] to [toChapter]. It updates [fromChapter]
 | 
			
		||||
     * on the database.
 | 
			
		||||
     */
 | 
			
		||||
    private fun onChapterChanged(fromChapter: ReaderChapter) {
 | 
			
		||||
        saveChapterProgress(fromChapter)
 | 
			
		||||
        saveChapterHistory(fromChapter)
 | 
			
		||||
    fun saveCurrentChapterReadingProgress() {
 | 
			
		||||
        getCurrentChapter()?.let { saveReadingProgress(it) }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Saves this [chapter] progress (last read page and whether it's read).
 | 
			
		||||
     * Called when reader chapter is changed in reader or when activity is paused.
 | 
			
		||||
     */
 | 
			
		||||
    private fun saveReadingProgress(readerChapter: ReaderChapter) {
 | 
			
		||||
        launchIO {
 | 
			
		||||
            saveChapterProgress(readerChapter)
 | 
			
		||||
            saveChapterHistory(readerChapter)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user