浏览代码

Use SQLDelight for all Chapter related queries (#7440)

Andreas 2 年之前
父节点
当前提交
29633b64aa

+ 4 - 0
app/src/main/java/eu/kanade/data/chapter/ChapterRepositoryImpl.kt

@@ -99,4 +99,8 @@ class ChapterRepositoryImpl(
     override suspend fun getChapterByMangaIdAsFlow(mangaId: Long): Flow<List<Chapter>> {
         return handler.subscribeToList { chaptersQueries.getChaptersByMangaId(mangaId, chapterMapper) }
     }
+
+    override suspend fun getChapterByUrlAndMangaId(url: String, mangaId: Long): Chapter? {
+        return handler.awaitOneOrNull { chaptersQueries.getChapterByUrlAndMangaId(url, mangaId, chapterMapper) }
+    }
 }

+ 9 - 0
app/src/main/java/eu/kanade/domain/chapter/interactor/GetChapter.kt

@@ -17,4 +17,13 @@ class GetChapter(
             null
         }
     }
+
+    suspend fun await(url: String, mangaId: Long): Chapter? {
+        return try {
+            chapterRepository.getChapterByUrlAndMangaId(url, mangaId)
+        } catch (e: Exception) {
+            logcat(LogPriority.ERROR, e)
+            null
+        }
+    }
 }

+ 2 - 0
app/src/main/java/eu/kanade/domain/chapter/repository/ChapterRepository.kt

@@ -19,4 +19,6 @@ interface ChapterRepository {
     suspend fun getChapterById(id: Long): Chapter?
 
     suspend fun getChapterByMangaIdAsFlow(mangaId: Long): Flow<List<Chapter>>
+
+    suspend fun getChapterByUrlAndMangaId(url: String, mangaId: Long): Chapter?
 }

+ 1 - 2
app/src/main/java/eu/kanade/tachiyomi/data/database/DatabaseHelper.kt

@@ -8,7 +8,6 @@ import eu.kanade.tachiyomi.data.database.mappers.MangaTypeMapping
 import eu.kanade.tachiyomi.data.database.models.Chapter
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.database.models.MangaCategory
-import eu.kanade.tachiyomi.data.database.queries.ChapterQueries
 import eu.kanade.tachiyomi.data.database.queries.MangaCategoryQueries
 import eu.kanade.tachiyomi.data.database.queries.MangaQueries
 
@@ -18,7 +17,7 @@ import eu.kanade.tachiyomi.data.database.queries.MangaQueries
 class DatabaseHelper(
     openHelper: SupportSQLiteOpenHelper,
 ) :
-    MangaQueries, ChapterQueries, MangaCategoryQueries {
+    MangaQueries, MangaCategoryQueries {
 
     override val db = DefaultStorIOSQLite.builder()
         .sqliteOpenHelper(openHelper)

+ 0 - 37
app/src/main/java/eu/kanade/tachiyomi/data/database/queries/ChapterQueries.kt

@@ -1,37 +0,0 @@
-package eu.kanade.tachiyomi.data.database.queries
-
-import com.pushtorefresh.storio.sqlite.queries.Query
-import eu.kanade.tachiyomi.data.database.DbProvider
-import eu.kanade.tachiyomi.data.database.models.Chapter
-import eu.kanade.tachiyomi.data.database.resolvers.ChapterProgressPutResolver
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable
-
-interface ChapterQueries : DbProvider {
-
-    fun getChapter(id: Long) = db.get()
-        .`object`(Chapter::class.java)
-        .withQuery(
-            Query.builder()
-                .table(ChapterTable.TABLE)
-                .where("${ChapterTable.COL_ID} = ?")
-                .whereArgs(id)
-                .build(),
-        )
-        .prepare()
-
-    fun getChapter(url: String, mangaId: Long) = db.get()
-        .`object`(Chapter::class.java)
-        .withQuery(
-            Query.builder()
-                .table(ChapterTable.TABLE)
-                .where("${ChapterTable.COL_URL} = ? AND ${ChapterTable.COL_MANGA_ID} = ?")
-                .whereArgs(url, mangaId)
-                .build(),
-        )
-        .prepare()
-
-    fun updateChapterProgress(chapter: Chapter) = db.put()
-        .`object`(chapter)
-        .withPutResolver(ChapterProgressPutResolver())
-        .prepare()
-}

+ 10 - 4
app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadStore.kt

@@ -2,11 +2,15 @@ package eu.kanade.tachiyomi.data.download
 
 import android.content.Context
 import androidx.core.content.edit
-import eu.kanade.tachiyomi.data.database.DatabaseHelper
+import eu.kanade.domain.chapter.interactor.GetChapter
+import eu.kanade.domain.chapter.model.toDbChapter
+import eu.kanade.domain.manga.interactor.GetMangaById
+import eu.kanade.domain.manga.model.toDbManga
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.download.model.Download
 import eu.kanade.tachiyomi.source.SourceManager
 import eu.kanade.tachiyomi.source.online.HttpSource
+import kotlinx.coroutines.runBlocking
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.decodeFromString
 import kotlinx.serialization.encodeToString
@@ -29,7 +33,9 @@ class DownloadStore(
     private val preferences = context.getSharedPreferences("active_downloads", Context.MODE_PRIVATE)
 
     private val json: Json by injectLazy()
-    private val db: DatabaseHelper by injectLazy()
+
+    private val getMangaById: GetMangaById by injectLazy()
+    private val getChapter: GetChapter by injectLazy()
 
     /**
      * Counter used to keep the queue order.
@@ -90,10 +96,10 @@ class DownloadStore(
             val cachedManga = mutableMapOf<Long, Manga?>()
             for ((mangaId, chapterId) in objs) {
                 val manga = cachedManga.getOrPut(mangaId) {
-                    db.getManga(mangaId).executeAsBlocking()
+                    runBlocking { getMangaById.await(mangaId)?.toDbManga() }
                 } ?: continue
                 val source = sourceManager.get(manga.source) as? HttpSource ?: continue
-                val chapter = db.getChapter(chapterId).executeAsBlocking() ?: continue
+                val chapter = runBlocking { getChapter.await(chapterId) }?.toDbChapter() ?: continue
                 downloads.add(Download(source, manga, chapter))
             }
         }

+ 22 - 16
app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt

@@ -7,9 +7,14 @@ import android.content.Intent
 import android.net.Uri
 import android.os.Build
 import androidx.core.content.ContextCompat
+import eu.kanade.domain.chapter.interactor.GetChapter
+import eu.kanade.domain.chapter.interactor.UpdateChapter
+import eu.kanade.domain.chapter.model.toChapterUpdate
+import eu.kanade.domain.chapter.model.toDbChapter
+import eu.kanade.domain.manga.interactor.GetMangaById
+import eu.kanade.domain.manga.model.toDbManga
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.backup.BackupRestoreService
-import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Chapter
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.download.DownloadManager
@@ -27,6 +32,7 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat
 import eu.kanade.tachiyomi.util.system.notificationManager
 import eu.kanade.tachiyomi.util.system.toShareIntent
 import eu.kanade.tachiyomi.util.system.toast
+import kotlinx.coroutines.runBlocking
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 import uy.kohesive.injekt.injectLazy
@@ -40,6 +46,9 @@ import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
  */
 class NotificationReceiver : BroadcastReceiver() {
 
+    private val getMangaById: GetMangaById by injectLazy()
+    private val getChapter: GetChapter by injectLazy()
+    private val updateChapter: UpdateChapter by injectLazy()
     private val downloadManager: DownloadManager by injectLazy()
 
     override fun onReceive(context: Context, intent: Intent) {
@@ -169,9 +178,8 @@ class NotificationReceiver : BroadcastReceiver() {
      * @param chapterId id of chapter
      */
     private fun openChapter(context: Context, mangaId: Long, chapterId: Long) {
-        val db = Injekt.get<DatabaseHelper>()
-        val manga = db.getManga(mangaId).executeAsBlocking()
-        val chapter = db.getChapter(chapterId).executeAsBlocking()
+        val manga = runBlocking { getMangaById.await(mangaId) }
+        val chapter = runBlocking { getChapter.await(chapterId) }
         if (manga != null && chapter != null) {
             val intent = ReaderActivity.newIntent(context, manga.id, chapter.id).apply {
                 flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
@@ -232,25 +240,25 @@ class NotificationReceiver : BroadcastReceiver() {
      * @param mangaId id of manga
      */
     private fun markAsRead(chapterUrls: Array<String>, mangaId: Long) {
-        val db: DatabaseHelper = Injekt.get()
         val preferences: PreferencesHelper = Injekt.get()
         val sourceManager: SourceManager = Injekt.get()
 
         launchIO {
-            chapterUrls.mapNotNull { db.getChapter(it, mangaId).executeAsBlocking() }
-                .forEach {
-                    it.read = true
-                    db.updateChapterProgress(it).executeAsBlocking()
+            val toUpdate = chapterUrls.mapNotNull { getChapter.await(it, mangaId) }
+                .map {
+                    val chapter = it.copy(read = true)
                     if (preferences.removeAfterMarkedAsRead()) {
-                        val manga = db.getManga(mangaId).executeAsBlocking()
+                        val manga = getMangaById.await(mangaId)
                         if (manga != null) {
                             val source = sourceManager.get(manga.source)
                             if (source != null) {
-                                downloadManager.deleteChapters(listOf(it), manga, source)
+                                downloadManager.deleteChapters(listOf(it.toDbChapter()), manga.toDbManga(), source)
                             }
                         }
                     }
+                    chapter.toChapterUpdate()
                 }
+            updateChapter.awaitAll(toUpdate)
         }
     }
 
@@ -261,12 +269,10 @@ class NotificationReceiver : BroadcastReceiver() {
      * @param mangaId id of manga
      */
     private fun downloadChapters(chapterUrls: Array<String>, mangaId: Long) {
-        val db: DatabaseHelper = Injekt.get()
-
         launchIO {
-            val chapters = chapterUrls.mapNotNull { db.getChapter(it, mangaId).executeAsBlocking() }
-            val manga = db.getManga(mangaId).executeAsBlocking()
-            if (chapters.isNotEmpty() && manga != null) {
+            val manga = getMangaById.await(mangaId)?.toDbManga()
+            val chapters = chapterUrls.mapNotNull { getChapter.await(it, mangaId)?.toDbChapter() }
+            if (manga != null && chapters.isNotEmpty()) {
                 downloadManager.downloadChapters(manga, chapters)
             }
         }

+ 9 - 6
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt

@@ -540,13 +540,16 @@ class ReaderPresenter(
      * Bookmarks the currently active chapter.
      */
     fun bookmarkCurrentChapter(bookmarked: Boolean) {
-        if (getCurrentChapter()?.chapter == null) {
-            return
+        val chapter = getCurrentChapter()?.chapter ?: return
+        chapter.bookmark = bookmarked // Otherwise the bookmark icon doesn't update
+        launchIO {
+            updateChapter.await(
+                ChapterUpdate(
+                    id = chapter.id!!.toLong(),
+                    bookmark = bookmarked,
+                ),
+            )
         }
-
-        val chapter = getCurrentChapter()?.chapter!!
-        chapter.bookmark = bookmarked
-        db.updateChapterProgress(chapter).executeAsBlocking()
     }
 
     /**

+ 6 - 0
app/src/main/sqldelight/data/chapters.sq

@@ -33,6 +33,12 @@ SELECT *
 FROM chapters
 WHERE url = :chapterUrl;
 
+getChapterByUrlAndMangaId:
+SELECT *
+FROM chapters
+WHERE url = :chapterUrl
+AND manga_id = :mangaId;
+
 removeChaptersWithIds:
 DELETE FROM chapters
 WHERE _id IN :chapterIds;