Explorar el Código

Use SQLDelight for all Manga related queries (#7447)

Andreas hace 2 años
padre
commit
17951cfd68
Se han modificado 42 ficheros con 342 adiciones y 752 borrados
  1. 1 5
      app/build.gradle.kts
  2. 27 0
      app/src/main/java/eu/kanade/data/manga/MangaMapper.kt
  3. 37 3
      app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt
  4. 8 2
      app/src/main/java/eu/kanade/domain/DomainModule.kt
  5. 18 0
      app/src/main/java/eu/kanade/domain/manga/interactor/GetLibraryManga.kt
  6. 6 2
      app/src/main/java/eu/kanade/domain/manga/interactor/GetManga.kt
  7. 1 1
      app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaWithChapters.kt
  8. 13 0
      app/src/main/java/eu/kanade/domain/manga/interactor/InsertManga.kt
  9. 33 0
      app/src/main/java/eu/kanade/domain/manga/interactor/SetMangaViewerFlags.kt
  10. 22 0
      app/src/main/java/eu/kanade/domain/manga/model/Manga.kt
  11. 9 2
      app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt
  12. 0 5
      app/src/main/java/eu/kanade/tachiyomi/AppModule.kt
  13. 0 27
      app/src/main/java/eu/kanade/tachiyomi/data/database/DatabaseHelper.kt
  14. 0 24
      app/src/main/java/eu/kanade/tachiyomi/data/database/DbExtensions.kt
  15. 0 7
      app/src/main/java/eu/kanade/tachiyomi/data/database/DbProvider.kt
  16. 0 88
      app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt
  17. 0 60
      app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaCategoryTypeMapping.kt
  18. 0 109
      app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt
  19. 0 77
      app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt
  20. 0 37
      app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt
  21. 0 34
      app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/ChapterProgressPutResolver.kt
  22. 0 25
      app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt
  23. 0 33
      app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt
  24. 0 6
      app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt
  25. 0 30
      app/src/main/java/eu/kanade/tachiyomi/data/database/tables/ChapterTable.kt
  26. 0 12
      app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaCategoryTable.kt
  27. 0 50
      app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaTable.kt
  28. 0 2
      app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt
  29. 3 3
      app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadStore.kt
  30. 3 3
      app/src/main/java/eu/kanade/tachiyomi/data/download/model/Download.kt
  31. 17 8
      app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt
  32. 5 5
      app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt
  33. 3 3
      app/src/main/java/eu/kanade/tachiyomi/data/track/job/DelayedTrackingUpdateJob.kt
  34. 8 4
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt
  35. 28 10
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt
  36. 20 9
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt
  37. 3 30
      app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
  38. 1 1
      app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
  39. 3 3
      app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFullCoverDialog.kt
  40. 11 7
      app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
  41. 24 25
      app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt
  42. 38 0
      app/src/main/sqldelight/data/mangas.sq

+ 1 - 5
app/build.gradle.kts

@@ -165,6 +165,7 @@ dependencies {
     implementation(androidx.paging.runtime)
     implementation(androidx.paging.compose)
 
+    implementation(libs.bundles.sqlite)
     implementation(androidx.sqlite)
     implementation(libs.sqldelight.android.driver)
     implementation(libs.sqldelight.coroutines)
@@ -218,11 +219,6 @@ dependencies {
     implementation(libs.unifile)
     implementation(libs.junrar)
 
-    // Database
-    implementation(libs.bundles.sqlite)
-    implementation("com.github.inorichi.storio:storio-common:8be19de@aar")
-    implementation("com.github.inorichi.storio:storio-sqlite:8be19de@aar")
-
     // Preferences
     implementation(libs.preferencektx)
     implementation(libs.flowpreferences)

+ 27 - 0
app/src/main/java/eu/kanade/data/manga/MangaMapper.kt

@@ -2,6 +2,7 @@ package eu.kanade.data.manga
 
 import eu.kanade.domain.chapter.model.Chapter
 import eu.kanade.domain.manga.model.Manga
+import eu.kanade.tachiyomi.data.database.models.LibraryManga
 
 val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long) -> Manga =
     { id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, _, initialized, viewer, chapterFlags, coverLastModified, dateAdded ->
@@ -61,3 +62,29 @@ val mangaChapterMapper: (Long, Long, String, String?, String?, String?, List<Str
             scanlator = scanlator,
         )
     }
+
+val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, Long, Long, Long) -> LibraryManga =
+    { _id, source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, unread_count, read_count, category ->
+        LibraryManga().apply {
+            this.id = _id
+            this.source = source
+            this.url = url
+            this.artist = artist
+            this.author = author
+            this.description = description
+            this.genre = genre?.joinToString()
+            this.title = title
+            this.status = status.toInt()
+            this.thumbnail_url = thumbnail_url
+            this.favorite = favorite
+            this.last_update = last_update ?: 0
+            this.initialized = initialized
+            this.viewer_flags = viewer.toInt()
+            this.chapter_flags = chapter_flags.toInt()
+            this.cover_last_modified = cover_last_modified
+            this.date_added = date_added
+            this.unreadCount = unread_count.toInt()
+            this.readCount = read_count.toInt()
+            this.category = category.toInt()
+        }
+    }

+ 37 - 3
app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt

@@ -6,6 +6,7 @@ import eu.kanade.data.toLong
 import eu.kanade.domain.manga.model.Manga
 import eu.kanade.domain.manga.model.MangaUpdate
 import eu.kanade.domain.manga.repository.MangaRepository
+import eu.kanade.tachiyomi.data.database.models.LibraryManga
 import eu.kanade.tachiyomi.util.system.logcat
 import kotlinx.coroutines.flow.Flow
 import logcat.LogPriority
@@ -18,18 +19,26 @@ class MangaRepositoryImpl(
         return handler.awaitOne { mangasQueries.getMangaById(id, mangaMapper) }
     }
 
-    override suspend fun subscribeMangaById(id: Long): Flow<Manga> {
+    override suspend fun getMangaByIdAsFlow(id: Long): Flow<Manga> {
         return handler.subscribeToOne { mangasQueries.getMangaById(id, mangaMapper) }
     }
 
-    override suspend fun getMangaByIdAsFlow(id: Long): Flow<Manga> {
-        return handler.subscribeToOne { mangasQueries.getMangaById(id, mangaMapper) }
+    override suspend fun getMangaByUrlAndSourceId(url: String, sourceId: Long): Manga? {
+        return handler.awaitOneOrNull { mangasQueries.getMangaByUrlAndSource(url, sourceId, mangaMapper) }
     }
 
     override suspend fun getFavorites(): List<Manga> {
         return handler.awaitList { mangasQueries.getFavorites(mangaMapper) }
     }
 
+    override suspend fun getLibraryManga(): List<LibraryManga> {
+        return handler.awaitList { mangasQueries.getLibrary(libraryManga) }
+    }
+
+    override fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>> {
+        return handler.subscribeToList { mangasQueries.getLibrary(libraryManga) }
+    }
+
     override fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> {
         return handler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) }
     }
@@ -59,6 +68,31 @@ class MangaRepositoryImpl(
         }
     }
 
+    override suspend fun insert(manga: Manga): Long? {
+        return handler.awaitOneOrNull {
+            mangasQueries.insert(
+                source = manga.source,
+                url = manga.url,
+                artist = manga.artist,
+                author = manga.author,
+                description = manga.description,
+                genre = manga.genre,
+                title = manga.title,
+                status = manga.status,
+                thumbnail_url = manga.thumbnailUrl,
+                favorite = manga.favorite,
+                last_update = manga.lastUpdate,
+                next_update = null,
+                initialized = manga.initialized,
+                viewer = manga.viewerFlags,
+                chapter_flags = manga.chapterFlags,
+                cover_last_modified = manga.coverLastModified,
+                date_added = manga.dateAdded,
+            )
+            mangasQueries.selectLastInsertedRowId()
+        }
+    }
+
     override suspend fun update(update: MangaUpdate): Boolean {
         return try {
             partialUpdate(update)

+ 8 - 2
app/src/main/java/eu/kanade/domain/DomainModule.kt

@@ -32,10 +32,13 @@ import eu.kanade.domain.history.interactor.UpsertHistory
 import eu.kanade.domain.history.repository.HistoryRepository
 import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
 import eu.kanade.domain.manga.interactor.GetFavorites
-import eu.kanade.domain.manga.interactor.GetMangaById
+import eu.kanade.domain.manga.interactor.GetLibraryManga
+import eu.kanade.domain.manga.interactor.GetManga
 import eu.kanade.domain.manga.interactor.GetMangaWithChapters
+import eu.kanade.domain.manga.interactor.InsertManga
 import eu.kanade.domain.manga.interactor.ResetViewerFlags
 import eu.kanade.domain.manga.interactor.SetMangaChapterFlags
+import eu.kanade.domain.manga.interactor.SetMangaViewerFlags
 import eu.kanade.domain.manga.interactor.UpdateManga
 import eu.kanade.domain.manga.repository.MangaRepository
 import eu.kanade.domain.source.interactor.GetEnabledSources
@@ -71,11 +74,14 @@ class DomainModule : InjektModule {
         addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) }
         addFactory { GetDuplicateLibraryManga(get()) }
         addFactory { GetFavorites(get()) }
+        addFactory { GetLibraryManga(get()) }
         addFactory { GetMangaWithChapters(get(), get()) }
-        addFactory { GetMangaById(get()) }
+        addFactory { GetManga(get()) }
         addFactory { GetNextChapter(get()) }
         addFactory { ResetViewerFlags(get()) }
         addFactory { SetMangaChapterFlags(get()) }
+        addFactory { SetMangaViewerFlags(get()) }
+        addFactory { InsertManga(get()) }
         addFactory { UpdateManga(get()) }
         addFactory { SetMangaCategories(get()) }
 

+ 18 - 0
app/src/main/java/eu/kanade/domain/manga/interactor/GetLibraryManga.kt

@@ -0,0 +1,18 @@
+package eu.kanade.domain.manga.interactor
+
+import eu.kanade.domain.manga.repository.MangaRepository
+import eu.kanade.tachiyomi.data.database.models.LibraryManga
+import kotlinx.coroutines.flow.Flow
+
+class GetLibraryManga(
+    private val mangaRepository: MangaRepository,
+) {
+
+    suspend fun await(): List<LibraryManga> {
+        return mangaRepository.getLibraryManga()
+    }
+
+    fun subscribe(): Flow<List<LibraryManga>> {
+        return mangaRepository.getLibraryMangaAsFlow()
+    }
+}

+ 6 - 2
app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaById.kt → app/src/main/java/eu/kanade/domain/manga/interactor/GetManga.kt

@@ -6,7 +6,7 @@ import eu.kanade.tachiyomi.util.system.logcat
 import kotlinx.coroutines.flow.Flow
 import logcat.LogPriority
 
-class GetMangaById(
+class GetManga(
     private val mangaRepository: MangaRepository,
 ) {
 
@@ -20,6 +20,10 @@ class GetMangaById(
     }
 
     suspend fun subscribe(id: Long): Flow<Manga> {
-        return mangaRepository.subscribeMangaById(id)
+        return mangaRepository.getMangaByIdAsFlow(id)
+    }
+
+    suspend fun await(url: String, sourceId: Long): Manga? {
+        return mangaRepository.getMangaByUrlAndSourceId(url, sourceId)
     }
 }

+ 1 - 1
app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaWithChapters.kt

@@ -14,7 +14,7 @@ class GetMangaWithChapters(
 
     suspend fun subscribe(id: Long): Flow<Pair<Manga, List<Chapter>>> {
         return combine(
-            mangaRepository.subscribeMangaById(id),
+            mangaRepository.getMangaByIdAsFlow(id),
             chapterRepository.getChapterByMangaIdAsFlow(id),
         ) { manga, chapters ->
             Pair(manga, chapters)

+ 13 - 0
app/src/main/java/eu/kanade/domain/manga/interactor/InsertManga.kt

@@ -0,0 +1,13 @@
+package eu.kanade.domain.manga.interactor
+
+import eu.kanade.domain.manga.model.Manga
+import eu.kanade.domain.manga.repository.MangaRepository
+
+class InsertManga(
+    private val mangaRepository: MangaRepository,
+) {
+
+    suspend fun await(manga: Manga): Long? {
+        return mangaRepository.insert(manga)
+    }
+}

+ 33 - 0
app/src/main/java/eu/kanade/domain/manga/interactor/SetMangaViewerFlags.kt

@@ -0,0 +1,33 @@
+package eu.kanade.domain.manga.interactor
+
+import eu.kanade.domain.manga.model.MangaUpdate
+import eu.kanade.domain.manga.repository.MangaRepository
+import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
+import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
+
+class SetMangaViewerFlags(
+    private val mangaRepository: MangaRepository,
+) {
+
+    suspend fun awaitSetMangaReadingMode(id: Long, flag: Long) {
+        mangaRepository.update(
+            MangaUpdate(
+                id = id,
+                viewerFlags = flag.setFlag(flag, ReadingModeType.MASK.toLong()),
+            ),
+        )
+    }
+
+    suspend fun awaitSetOrientationType(id: Long, flag: Long) {
+        mangaRepository.update(
+            MangaUpdate(
+                id = id,
+                viewerFlags = flag.setFlag(flag, OrientationType.MASK.toLong()),
+            ),
+        )
+    }
+
+    private fun Long.setFlag(flag: Long, mask: Long): Long {
+        return this and mask.inv() or (flag and mask)
+    }
+}

+ 22 - 0
app/src/main/java/eu/kanade/domain/manga/model/Manga.kt

@@ -175,6 +175,28 @@ fun Manga.toMangaInfo(): MangaInfo = MangaInfo(
     title = title,
 )
 
+fun Manga.toMangaUpdate(): MangaUpdate {
+    return MangaUpdate(
+        id = id,
+        source = source,
+        favorite = favorite,
+        lastUpdate = lastUpdate,
+        dateAdded = dateAdded,
+        viewerFlags = viewerFlags,
+        chapterFlags = chapterFlags,
+        coverLastModified = coverLastModified,
+        url = url,
+        title = title,
+        artist = artist,
+        author = author,
+        description = description,
+        genre = genre,
+        status = status,
+        thumbnailUrl = thumbnailUrl,
+        initialized = initialized,
+    )
+}
+
 fun Manga.isLocal(): Boolean = source == LocalSource.ID
 
 fun Manga.hasCustomCover(coverCache: CoverCache = Injekt.get()): Boolean {

+ 9 - 2
app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt

@@ -2,18 +2,23 @@ package eu.kanade.domain.manga.repository
 
 import eu.kanade.domain.manga.model.Manga
 import eu.kanade.domain.manga.model.MangaUpdate
+import eu.kanade.tachiyomi.data.database.models.LibraryManga
 import kotlinx.coroutines.flow.Flow
 
 interface MangaRepository {
 
     suspend fun getMangaById(id: Long): Manga
 
-    suspend fun subscribeMangaById(id: Long): Flow<Manga>
-
     suspend fun getMangaByIdAsFlow(id: Long): Flow<Manga>
 
+    suspend fun getMangaByUrlAndSourceId(url: String, sourceId: Long): Manga?
+
     suspend fun getFavorites(): List<Manga>
 
+    suspend fun getLibraryManga(): List<LibraryManga>
+
+    fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>>
+
     fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>>
 
     suspend fun getDuplicateLibraryManga(title: String, sourceId: Long): Manga?
@@ -22,6 +27,8 @@ interface MangaRepository {
 
     suspend fun setMangaCategories(mangaId: Long, categoryIds: List<Long>)
 
+    suspend fun insert(manga: Manga): Long?
+
     suspend fun update(update: MangaUpdate): Boolean
 
     suspend fun updateAll(values: List<MangaUpdate>): Boolean

+ 0 - 5
app/src/main/java/eu/kanade/tachiyomi/AppModule.kt

@@ -15,7 +15,6 @@ import eu.kanade.data.dateAdapter
 import eu.kanade.data.listOfStringsAdapter
 import eu.kanade.tachiyomi.data.cache.ChapterCache
 import eu.kanade.tachiyomi.data.cache.CoverCache
-import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.DbOpenCallback
 import eu.kanade.tachiyomi.data.download.DownloadManager
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@@ -76,8 +75,6 @@ class AppModule(val app: Application) : InjektModule {
 
         addSingletonFactory { PreferencesHelper(app) }
 
-        addSingletonFactory { DatabaseHelper(get()) }
-
         addSingletonFactory { ChapterCache(app) }
 
         addSingletonFactory { CoverCache(app) }
@@ -106,8 +103,6 @@ class AppModule(val app: Application) : InjektModule {
 
             get<Database>()
 
-            get<DatabaseHelper>()
-
             get<DownloadManager>()
         }
     }

+ 0 - 27
app/src/main/java/eu/kanade/tachiyomi/data/database/DatabaseHelper.kt

@@ -1,27 +0,0 @@
-package eu.kanade.tachiyomi.data.database
-
-import androidx.sqlite.db.SupportSQLiteOpenHelper
-import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite
-import eu.kanade.tachiyomi.data.database.mappers.ChapterTypeMapping
-import eu.kanade.tachiyomi.data.database.mappers.MangaCategoryTypeMapping
-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.MangaQueries
-
-/**
- * This class provides operations to manage the database through its interfaces.
- */
-class DatabaseHelper(
-    openHelper: SupportSQLiteOpenHelper,
-) :
-    MangaQueries {
-
-    override val db = DefaultStorIOSQLite.builder()
-        .sqliteOpenHelper(openHelper)
-        .addTypeMapping(Manga::class.java, MangaTypeMapping())
-        .addTypeMapping(Chapter::class.java, ChapterTypeMapping())
-        .addTypeMapping(MangaCategory::class.java, MangaCategoryTypeMapping())
-        .build()
-}

+ 0 - 24
app/src/main/java/eu/kanade/tachiyomi/data/database/DbExtensions.kt

@@ -1,24 +0,0 @@
-package eu.kanade.tachiyomi.data.database
-
-import com.pushtorefresh.storio.sqlite.StorIOSQLite
-
-inline fun StorIOSQLite.inTransaction(block: () -> Unit) {
-    lowLevel().beginTransaction()
-    try {
-        block()
-        lowLevel().setTransactionSuccessful()
-    } finally {
-        lowLevel().endTransaction()
-    }
-}
-
-inline fun <T> StorIOSQLite.inTransactionReturn(block: () -> T): T {
-    lowLevel().beginTransaction()
-    try {
-        val result = block()
-        lowLevel().setTransactionSuccessful()
-        return result
-    } finally {
-        lowLevel().endTransaction()
-    }
-}

+ 0 - 7
app/src/main/java/eu/kanade/tachiyomi/data/database/DbProvider.kt

@@ -1,7 +0,0 @@
-package eu.kanade.tachiyomi.data.database
-
-import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite
-
-interface DbProvider {
-    val db: DefaultStorIOSQLite
-}

+ 0 - 88
app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt

@@ -1,88 +0,0 @@
-package eu.kanade.tachiyomi.data.database.mappers
-
-import android.database.Cursor
-import androidx.core.content.contentValuesOf
-import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
-import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver
-import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
-import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver
-import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
-import com.pushtorefresh.storio.sqlite.queries.InsertQuery
-import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
-import eu.kanade.tachiyomi.data.database.models.Chapter
-import eu.kanade.tachiyomi.data.database.models.ChapterImpl
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_BOOKMARK
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_CHAPTER_NUMBER
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_DATE_FETCH
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_DATE_UPLOAD
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_ID
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_LAST_PAGE_READ
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_MANGA_ID
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_NAME
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_READ
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_SCANLATOR
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_SOURCE_ORDER
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_URL
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable.TABLE
-
-class ChapterTypeMapping : SQLiteTypeMapping<Chapter>(
-    ChapterPutResolver(),
-    ChapterGetResolver(),
-    ChapterDeleteResolver(),
-)
-
-class ChapterPutResolver : DefaultPutResolver<Chapter>() {
-
-    override fun mapToInsertQuery(obj: Chapter) = InsertQuery.builder()
-        .table(TABLE)
-        .build()
-
-    override fun mapToUpdateQuery(obj: Chapter) = UpdateQuery.builder()
-        .table(TABLE)
-        .where("$COL_ID = ?")
-        .whereArgs(obj.id)
-        .build()
-
-    override fun mapToContentValues(obj: Chapter) =
-        contentValuesOf(
-            COL_ID to obj.id,
-            COL_MANGA_ID to obj.manga_id,
-            COL_URL to obj.url,
-            COL_NAME to obj.name,
-            COL_READ to obj.read,
-            COL_SCANLATOR to obj.scanlator,
-            COL_BOOKMARK to obj.bookmark,
-            COL_DATE_FETCH to obj.date_fetch,
-            COL_DATE_UPLOAD to obj.date_upload,
-            COL_LAST_PAGE_READ to obj.last_page_read,
-            COL_CHAPTER_NUMBER to obj.chapter_number,
-            COL_SOURCE_ORDER to obj.source_order,
-        )
-}
-
-class ChapterGetResolver : DefaultGetResolver<Chapter>() {
-
-    override fun mapFromCursor(cursor: Cursor): Chapter = ChapterImpl().apply {
-        id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID))
-        manga_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MANGA_ID))
-        url = cursor.getString(cursor.getColumnIndexOrThrow(COL_URL))
-        name = cursor.getString(cursor.getColumnIndexOrThrow(COL_NAME))
-        scanlator = cursor.getString(cursor.getColumnIndexOrThrow(COL_SCANLATOR))
-        read = cursor.getInt(cursor.getColumnIndexOrThrow(COL_READ)) == 1
-        bookmark = cursor.getInt(cursor.getColumnIndexOrThrow(COL_BOOKMARK)) == 1
-        date_fetch = cursor.getLong(cursor.getColumnIndexOrThrow(COL_DATE_FETCH))
-        date_upload = cursor.getLong(cursor.getColumnIndexOrThrow(COL_DATE_UPLOAD))
-        last_page_read = cursor.getInt(cursor.getColumnIndexOrThrow(COL_LAST_PAGE_READ))
-        chapter_number = cursor.getFloat(cursor.getColumnIndexOrThrow(COL_CHAPTER_NUMBER))
-        source_order = cursor.getInt(cursor.getColumnIndexOrThrow(COL_SOURCE_ORDER))
-    }
-}
-
-class ChapterDeleteResolver : DefaultDeleteResolver<Chapter>() {
-
-    override fun mapToDeleteQuery(obj: Chapter) = DeleteQuery.builder()
-        .table(TABLE)
-        .where("$COL_ID = ?")
-        .whereArgs(obj.id)
-        .build()
-}

+ 0 - 60
app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaCategoryTypeMapping.kt

@@ -1,60 +0,0 @@
-package eu.kanade.tachiyomi.data.database.mappers
-
-import android.database.Cursor
-import androidx.core.content.contentValuesOf
-import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
-import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver
-import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
-import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver
-import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
-import com.pushtorefresh.storio.sqlite.queries.InsertQuery
-import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
-import eu.kanade.tachiyomi.data.database.models.MangaCategory
-import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.COL_CATEGORY_ID
-import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.COL_ID
-import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.COL_MANGA_ID
-import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.TABLE
-
-class MangaCategoryTypeMapping : SQLiteTypeMapping<MangaCategory>(
-    MangaCategoryPutResolver(),
-    MangaCategoryGetResolver(),
-    MangaCategoryDeleteResolver(),
-)
-
-class MangaCategoryPutResolver : DefaultPutResolver<MangaCategory>() {
-
-    override fun mapToInsertQuery(obj: MangaCategory) = InsertQuery.builder()
-        .table(TABLE)
-        .build()
-
-    override fun mapToUpdateQuery(obj: MangaCategory) = UpdateQuery.builder()
-        .table(TABLE)
-        .where("$COL_ID = ?")
-        .whereArgs(obj.id)
-        .build()
-
-    override fun mapToContentValues(obj: MangaCategory) =
-        contentValuesOf(
-            COL_ID to obj.id,
-            COL_MANGA_ID to obj.manga_id,
-            COL_CATEGORY_ID to obj.category_id,
-        )
-}
-
-class MangaCategoryGetResolver : DefaultGetResolver<MangaCategory>() {
-
-    override fun mapFromCursor(cursor: Cursor): MangaCategory = MangaCategory().apply {
-        id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID))
-        manga_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MANGA_ID))
-        category_id = cursor.getInt(cursor.getColumnIndexOrThrow(COL_CATEGORY_ID))
-    }
-}
-
-class MangaCategoryDeleteResolver : DefaultDeleteResolver<MangaCategory>() {
-
-    override fun mapToDeleteQuery(obj: MangaCategory) = DeleteQuery.builder()
-        .table(TABLE)
-        .where("$COL_ID = ?")
-        .whereArgs(obj.id)
-        .build()
-}

+ 0 - 109
app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt

@@ -1,109 +0,0 @@
-package eu.kanade.tachiyomi.data.database.mappers
-
-import android.database.Cursor
-import androidx.core.content.contentValuesOf
-import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
-import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver
-import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
-import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver
-import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
-import com.pushtorefresh.storio.sqlite.queries.InsertQuery
-import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
-import eu.kanade.tachiyomi.data.database.models.Manga
-import eu.kanade.tachiyomi.data.database.models.MangaImpl
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_ARTIST
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_AUTHOR
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_CHAPTER_FLAGS
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_COVER_LAST_MODIFIED
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_DATE_ADDED
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_DESCRIPTION
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_FAVORITE
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_GENRE
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_ID
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_INITIALIZED
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_LAST_UPDATE
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_SOURCE
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_STATUS
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_THUMBNAIL_URL
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_TITLE
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_URL
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_VIEWER
-import eu.kanade.tachiyomi.data.database.tables.MangaTable.TABLE
-
-class MangaTypeMapping : SQLiteTypeMapping<Manga>(
-    MangaPutResolver(),
-    MangaGetResolver(),
-    MangaDeleteResolver(),
-)
-
-class MangaPutResolver : DefaultPutResolver<Manga>() {
-
-    override fun mapToInsertQuery(obj: Manga) = InsertQuery.builder()
-        .table(TABLE)
-        .build()
-
-    override fun mapToUpdateQuery(obj: Manga) = UpdateQuery.builder()
-        .table(TABLE)
-        .where("$COL_ID = ?")
-        .whereArgs(obj.id)
-        .build()
-
-    override fun mapToContentValues(obj: Manga) =
-        contentValuesOf(
-            COL_ID to obj.id,
-            COL_SOURCE to obj.source,
-            COL_URL to obj.url,
-            COL_ARTIST to obj.artist,
-            COL_AUTHOR to obj.author,
-            COL_DESCRIPTION to obj.description,
-            COL_GENRE to obj.genre,
-            COL_TITLE to obj.title,
-            COL_STATUS to obj.status,
-            COL_THUMBNAIL_URL to obj.thumbnail_url,
-            COL_FAVORITE to obj.favorite,
-            COL_LAST_UPDATE to obj.last_update,
-            COL_INITIALIZED to obj.initialized,
-            COL_VIEWER to obj.viewer_flags,
-            COL_CHAPTER_FLAGS to obj.chapter_flags,
-            COL_COVER_LAST_MODIFIED to obj.cover_last_modified,
-            COL_DATE_ADDED to obj.date_added,
-        )
-}
-
-interface BaseMangaGetResolver {
-    fun mapBaseFromCursor(manga: Manga, cursor: Cursor) = manga.apply {
-        id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID))
-        source = cursor.getLong(cursor.getColumnIndexOrThrow(COL_SOURCE))
-        url = cursor.getString(cursor.getColumnIndexOrThrow(COL_URL))
-        artist = cursor.getString(cursor.getColumnIndexOrThrow(COL_ARTIST))
-        author = cursor.getString(cursor.getColumnIndexOrThrow(COL_AUTHOR))
-        description = cursor.getString(cursor.getColumnIndexOrThrow(COL_DESCRIPTION))
-        genre = cursor.getString(cursor.getColumnIndexOrThrow(COL_GENRE))
-        title = cursor.getString(cursor.getColumnIndexOrThrow(COL_TITLE))
-        status = cursor.getInt(cursor.getColumnIndexOrThrow(COL_STATUS))
-        thumbnail_url = cursor.getString(cursor.getColumnIndexOrThrow(COL_THUMBNAIL_URL))
-        favorite = cursor.getInt(cursor.getColumnIndexOrThrow(COL_FAVORITE)) == 1
-        last_update = cursor.getLong(cursor.getColumnIndexOrThrow(COL_LAST_UPDATE))
-        initialized = cursor.getInt(cursor.getColumnIndexOrThrow(COL_INITIALIZED)) == 1
-        viewer_flags = cursor.getInt(cursor.getColumnIndexOrThrow(COL_VIEWER))
-        chapter_flags = cursor.getInt(cursor.getColumnIndexOrThrow(COL_CHAPTER_FLAGS))
-        cover_last_modified = cursor.getLong(cursor.getColumnIndexOrThrow(COL_COVER_LAST_MODIFIED))
-        date_added = cursor.getLong(cursor.getColumnIndexOrThrow(COL_DATE_ADDED))
-    }
-}
-
-open class MangaGetResolver : DefaultGetResolver<Manga>(), BaseMangaGetResolver {
-
-    override fun mapFromCursor(cursor: Cursor): Manga {
-        return mapBaseFromCursor(MangaImpl(), cursor)
-    }
-}
-
-class MangaDeleteResolver : DefaultDeleteResolver<Manga>() {
-
-    override fun mapToDeleteQuery(obj: Manga) = DeleteQuery.builder()
-        .table(TABLE)
-        .where("$COL_ID = ?")
-        .whereArgs(obj.id)
-        .build()
-}

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

@@ -1,77 +0,0 @@
-package eu.kanade.tachiyomi.data.database.queries
-
-import com.pushtorefresh.storio.sqlite.queries.Query
-import com.pushtorefresh.storio.sqlite.queries.RawQuery
-import eu.kanade.tachiyomi.data.database.DbProvider
-import eu.kanade.tachiyomi.data.database.models.LibraryManga
-import eu.kanade.tachiyomi.data.database.models.Manga
-import eu.kanade.tachiyomi.data.database.resolvers.LibraryMangaGetResolver
-import eu.kanade.tachiyomi.data.database.resolvers.MangaFlagsPutResolver
-import eu.kanade.tachiyomi.data.database.tables.CategoryTable
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable
-import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
-import eu.kanade.tachiyomi.data.database.tables.MangaTable
-
-interface MangaQueries : DbProvider {
-
-    fun getLibraryMangas() = db.get()
-        .listOfObjects(LibraryManga::class.java)
-        .withQuery(
-            RawQuery.builder()
-                .query(libraryQuery)
-                .observesTables(MangaTable.TABLE, ChapterTable.TABLE, MangaCategoryTable.TABLE, CategoryTable.TABLE)
-                .build(),
-        )
-        .withGetResolver(LibraryMangaGetResolver.INSTANCE)
-        .prepare()
-
-    fun getFavoriteMangas() = db.get()
-        .listOfObjects(Manga::class.java)
-        .withQuery(
-            Query.builder()
-                .table(MangaTable.TABLE)
-                .where("${MangaTable.COL_FAVORITE} = ?")
-                .whereArgs(1)
-                .build(),
-        )
-        .prepare()
-
-    fun getManga(url: String, sourceId: Long) = db.get()
-        .`object`(Manga::class.java)
-        .withQuery(
-            Query.builder()
-                .table(MangaTable.TABLE)
-                .where("${MangaTable.COL_URL} = ? AND ${MangaTable.COL_SOURCE} = ?")
-                .whereArgs(url, sourceId)
-                .build(),
-        )
-        .prepare()
-
-    fun getManga(id: Long) = db.get()
-        .`object`(Manga::class.java)
-        .withQuery(
-            Query.builder()
-                .table(MangaTable.TABLE)
-                .where("${MangaTable.COL_ID} = ?")
-                .whereArgs(id)
-                .build(),
-        )
-        .prepare()
-
-    fun insertManga(manga: Manga) = db.put().`object`(manga).prepare()
-
-    fun updateChapterFlags(manga: Manga) = db.put()
-        .`object`(manga)
-        .withPutResolver(MangaFlagsPutResolver(MangaTable.COL_CHAPTER_FLAGS, Manga::chapter_flags))
-        .prepare()
-
-    fun updateChapterFlags(manga: List<Manga>) = db.put()
-        .objects(manga)
-        .withPutResolver(MangaFlagsPutResolver(MangaTable.COL_CHAPTER_FLAGS, Manga::chapter_flags))
-        .prepare()
-
-    fun updateViewerFlags(manga: Manga) = db.put()
-        .`object`(manga)
-        .withPutResolver(MangaFlagsPutResolver(MangaTable.COL_VIEWER, Manga::viewer_flags))
-        .prepare()
-}

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

@@ -1,37 +0,0 @@
-package eu.kanade.tachiyomi.data.database.queries
-
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter
-import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory
-import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
-
-/**
- * Query to get the manga from the library, with their categories, read and unread count.
- */
-val libraryQuery =
-    """
-    SELECT M.*, COALESCE(MC.${MangaCategory.COL_CATEGORY_ID}, 0) AS ${Manga.COL_CATEGORY}
-    FROM (
-        SELECT ${Manga.TABLE}.*, COALESCE(C.unreadCount, 0) AS ${Manga.COMPUTED_COL_UNREAD_COUNT}, COALESCE(R.readCount, 0) AS ${Manga.COMPUTED_COL_READ_COUNT}
-        FROM ${Manga.TABLE}
-        LEFT JOIN (
-            SELECT ${Chapter.COL_MANGA_ID}, COUNT(*) AS unreadCount
-            FROM ${Chapter.TABLE}
-            WHERE ${Chapter.COL_READ} = 0
-            GROUP BY ${Chapter.COL_MANGA_ID}
-        ) AS C
-        ON ${Manga.COL_ID} = C.${Chapter.COL_MANGA_ID}
-        LEFT JOIN (
-            SELECT ${Chapter.COL_MANGA_ID}, COUNT(*) AS readCount
-            FROM ${Chapter.TABLE}
-            WHERE ${Chapter.COL_READ} = 1
-            GROUP BY ${Chapter.COL_MANGA_ID}
-        ) AS R
-        ON ${Manga.COL_ID} = R.${Chapter.COL_MANGA_ID}
-        WHERE ${Manga.COL_FAVORITE} = 1
-        GROUP BY ${Manga.COL_ID}
-        ORDER BY ${Manga.COL_TITLE}
-    ) AS M
-    LEFT JOIN (
-        SELECT * FROM ${MangaCategory.TABLE}) AS MC
-        ON MC.${MangaCategory.COL_MANGA_ID} = M.${Manga.COL_ID}
-"""

+ 0 - 34
app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/ChapterProgressPutResolver.kt

@@ -1,34 +0,0 @@
-package eu.kanade.tachiyomi.data.database.resolvers
-
-import androidx.core.content.contentValuesOf
-import com.pushtorefresh.storio.sqlite.StorIOSQLite
-import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
-import com.pushtorefresh.storio.sqlite.operations.put.PutResult
-import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
-import eu.kanade.tachiyomi.data.database.inTransactionReturn
-import eu.kanade.tachiyomi.data.database.models.Chapter
-import eu.kanade.tachiyomi.data.database.tables.ChapterTable
-
-class ChapterProgressPutResolver : PutResolver<Chapter>() {
-
-    override fun performPut(db: StorIOSQLite, chapter: Chapter) = db.inTransactionReturn {
-        val updateQuery = mapToUpdateQuery(chapter)
-        val contentValues = mapToContentValues(chapter)
-
-        val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
-        PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
-    }
-
-    fun mapToUpdateQuery(chapter: Chapter) = UpdateQuery.builder()
-        .table(ChapterTable.TABLE)
-        .where("${ChapterTable.COL_ID} = ?")
-        .whereArgs(chapter.id)
-        .build()
-
-    fun mapToContentValues(chapter: Chapter) =
-        contentValuesOf(
-            ChapterTable.COL_READ to chapter.read,
-            ChapterTable.COL_BOOKMARK to chapter.bookmark,
-            ChapterTable.COL_LAST_PAGE_READ to chapter.last_page_read,
-        )
-}

+ 0 - 25
app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt

@@ -1,25 +0,0 @@
-package eu.kanade.tachiyomi.data.database.resolvers
-
-import android.database.Cursor
-import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
-import eu.kanade.tachiyomi.data.database.mappers.BaseMangaGetResolver
-import eu.kanade.tachiyomi.data.database.models.LibraryManga
-import eu.kanade.tachiyomi.data.database.tables.MangaTable
-
-class LibraryMangaGetResolver : DefaultGetResolver<LibraryManga>(), BaseMangaGetResolver {
-
-    companion object {
-        val INSTANCE = LibraryMangaGetResolver()
-    }
-
-    override fun mapFromCursor(cursor: Cursor): LibraryManga {
-        val manga = LibraryManga()
-
-        mapBaseFromCursor(manga, cursor)
-        manga.unreadCount = cursor.getInt(cursor.getColumnIndexOrThrow(MangaTable.COMPUTED_COL_UNREAD_COUNT))
-        manga.category = cursor.getInt(cursor.getColumnIndexOrThrow(MangaTable.COL_CATEGORY))
-        manga.readCount = cursor.getInt(cursor.getColumnIndexOrThrow(MangaTable.COMPUTED_COL_READ_COUNT))
-
-        return manga
-    }
-}

+ 0 - 33
app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt

@@ -1,33 +0,0 @@
-package eu.kanade.tachiyomi.data.database.resolvers
-
-import androidx.core.content.contentValuesOf
-import com.pushtorefresh.storio.sqlite.StorIOSQLite
-import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
-import com.pushtorefresh.storio.sqlite.operations.put.PutResult
-import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
-import eu.kanade.tachiyomi.data.database.inTransactionReturn
-import eu.kanade.tachiyomi.data.database.models.Manga
-import eu.kanade.tachiyomi.data.database.tables.MangaTable
-import kotlin.reflect.KProperty1
-
-class MangaFlagsPutResolver(private val colName: String, private val fieldGetter: KProperty1<Manga, Int>) : PutResolver<Manga>() {
-
-    override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
-        val updateQuery = mapToUpdateQuery(manga)
-        val contentValues = mapToContentValues(manga)
-
-        val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
-        PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
-    }
-
-    fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder()
-        .table(MangaTable.TABLE)
-        .where("${MangaTable.COL_ID} = ?")
-        .whereArgs(manga.id)
-        .build()
-
-    fun mapToContentValues(manga: Manga) =
-        contentValuesOf(
-            colName to fieldGetter.get(manga),
-        )
-}

+ 0 - 6
app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt

@@ -1,6 +0,0 @@
-package eu.kanade.tachiyomi.data.database.tables
-
-object CategoryTable {
-
-    const val TABLE = "categories"
-}

+ 0 - 30
app/src/main/java/eu/kanade/tachiyomi/data/database/tables/ChapterTable.kt

@@ -1,30 +0,0 @@
-package eu.kanade.tachiyomi.data.database.tables
-
-object ChapterTable {
-
-    const val TABLE = "chapters"
-
-    const val COL_ID = "_id"
-
-    const val COL_MANGA_ID = "manga_id"
-
-    const val COL_URL = "url"
-
-    const val COL_NAME = "name"
-
-    const val COL_READ = "read"
-
-    const val COL_SCANLATOR = "scanlator"
-
-    const val COL_BOOKMARK = "bookmark"
-
-    const val COL_DATE_FETCH = "date_fetch"
-
-    const val COL_DATE_UPLOAD = "date_upload"
-
-    const val COL_LAST_PAGE_READ = "last_page_read"
-
-    const val COL_CHAPTER_NUMBER = "chapter_number"
-
-    const val COL_SOURCE_ORDER = "source_order"
-}

+ 0 - 12
app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaCategoryTable.kt

@@ -1,12 +0,0 @@
-package eu.kanade.tachiyomi.data.database.tables
-
-object MangaCategoryTable {
-
-    const val TABLE = "mangas_categories"
-
-    const val COL_ID = "_id"
-
-    const val COL_MANGA_ID = "manga_id"
-
-    const val COL_CATEGORY_ID = "category_id"
-}

+ 0 - 50
app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaTable.kt

@@ -1,50 +0,0 @@
-package eu.kanade.tachiyomi.data.database.tables
-
-object MangaTable {
-
-    const val TABLE = "mangas"
-
-    const val COL_ID = "_id"
-
-    const val COL_SOURCE = "source"
-
-    const val COL_URL = "url"
-
-    const val COL_ARTIST = "artist"
-
-    const val COL_AUTHOR = "author"
-
-    const val COL_DESCRIPTION = "description"
-
-    const val COL_GENRE = "genre"
-
-    const val COL_TITLE = "title"
-
-    const val COL_STATUS = "status"
-
-    const val COL_THUMBNAIL_URL = "thumbnail_url"
-
-    const val COL_FAVORITE = "favorite"
-
-    const val COL_LAST_UPDATE = "last_update"
-
-    // Not actually used anymore
-    const val COL_NEXT_UPDATE = "next_update"
-
-    const val COL_DATE_ADDED = "date_added"
-
-    const val COL_INITIALIZED = "initialized"
-
-    const val COL_VIEWER = "viewer"
-
-    const val COL_CHAPTER_FLAGS = "chapter_flags"
-
-    const val COL_CATEGORY = "category"
-
-    const val COL_COVER_LAST_MODIFIED = "cover_last_modified"
-
-    // Not an actual value but computed when created
-    const val COMPUTED_COL_UNREAD_COUNT = "unread_count"
-
-    const val COMPUTED_COL_READ_COUNT = "read_count"
-}

+ 0 - 2
app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt

@@ -5,7 +5,6 @@ import com.hippo.unifile.UniFile
 import com.jakewharton.rxrelay.BehaviorRelay
 import eu.kanade.domain.category.interactor.GetCategories
 import eu.kanade.tachiyomi.R
-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.model.Download
@@ -32,7 +31,6 @@ import uy.kohesive.injekt.injectLazy
  */
 class DownloadManager(
     private val context: Context,
-    private val db: DatabaseHelper = Injekt.get(),
     private val getCategories: GetCategories = Injekt.get(),
 ) {
 

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

@@ -4,7 +4,7 @@ import android.content.Context
 import androidx.core.content.edit
 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.interactor.GetManga
 import eu.kanade.domain.manga.model.toDbManga
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.download.model.Download
@@ -34,7 +34,7 @@ class DownloadStore(
 
     private val json: Json by injectLazy()
 
-    private val getMangaById: GetMangaById by injectLazy()
+    private val getManga: GetManga by injectLazy()
     private val getChapter: GetChapter by injectLazy()
 
     /**
@@ -96,7 +96,7 @@ class DownloadStore(
             val cachedManga = mutableMapOf<Long, Manga?>()
             for ((mangaId, chapterId) in objs) {
                 val manga = cachedManga.getOrPut(mangaId) {
-                    runBlocking { getMangaById.await(mangaId)?.toDbManga() }
+                    runBlocking { getManga.await(mangaId)?.toDbManga() }
                 } ?: continue
                 val source = sourceManager.get(manga.source) as? HttpSource ?: continue
                 val chapter = runBlocking { getChapter.await(chapterId) }?.toDbChapter() ?: continue

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/data/download/model/Download.kt

@@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.data.download.model
 
 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.interactor.GetManga
 import eu.kanade.domain.manga.model.toDbManga
 import eu.kanade.tachiyomi.data.database.models.Chapter
 import eu.kanade.tachiyomi.data.database.models.Manga
@@ -69,11 +69,11 @@ data class Download(
         suspend fun fromChapterId(
             chapterId: Long,
             getChapter: GetChapter = Injekt.get(),
-            getMangaById: GetMangaById = Injekt.get(),
+            getManga: GetManga = Injekt.get(),
             sourceManager: SourceManager = Injekt.get(),
         ): Download? {
             val chapter = getChapter.await(chapterId) ?: return null
-            val manga = getMangaById.await(chapter.mangaId) ?: return null
+            val manga = getManga.await(chapter.mangaId) ?: return null
             val source = sourceManager.get(manga.source) as? HttpSource ?: return null
 
             return Download(source, manga.toDbManga(), chapter.toDbChapter())

+ 17 - 8
app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt

@@ -13,16 +13,17 @@ import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
 import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
 import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
 import eu.kanade.domain.chapter.model.toDbChapter
-import eu.kanade.domain.manga.interactor.GetMangaById
+import eu.kanade.domain.manga.interactor.GetLibraryManga
+import eu.kanade.domain.manga.interactor.GetManga
 import eu.kanade.domain.manga.interactor.UpdateManga
 import eu.kanade.domain.manga.model.toMangaInfo
+import eu.kanade.domain.manga.model.toMangaUpdate
 import eu.kanade.domain.track.interactor.GetTracks
 import eu.kanade.domain.track.interactor.InsertTrack
 import eu.kanade.domain.track.model.toDbTrack
 import eu.kanade.domain.track.model.toDomainTrack
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.cache.CoverCache
-import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Chapter
 import eu.kanade.tachiyomi.data.database.models.LibraryManga
 import eu.kanade.tachiyomi.data.database.models.Manga
@@ -61,6 +62,7 @@ import kotlinx.coroutines.async
 import kotlinx.coroutines.awaitAll
 import kotlinx.coroutines.cancel
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.supervisorScope
 import kotlinx.coroutines.sync.Semaphore
 import kotlinx.coroutines.sync.withPermit
@@ -84,13 +86,13 @@ import eu.kanade.domain.manga.model.Manga as DomainManga
  * destroyed.
  */
 class LibraryUpdateService(
-    val db: DatabaseHelper = Injekt.get(),
     val sourceManager: SourceManager = Injekt.get(),
     val preferences: PreferencesHelper = Injekt.get(),
     val downloadManager: DownloadManager = Injekt.get(),
     val trackManager: TrackManager = Injekt.get(),
     val coverCache: CoverCache = Injekt.get(),
-    private val getMangaById: GetMangaById = Injekt.get(),
+    private val getLibraryManga: GetLibraryManga = Injekt.get(),
+    private val getManga: GetManga = Injekt.get(),
     private val updateManga: UpdateManga = Injekt.get(),
     private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
     private val getCategories: GetCategories = Injekt.get(),
@@ -255,7 +257,7 @@ class LibraryUpdateService(
      * @param categoryId the ID of the category to update, or -1 if no category specified.
      */
     fun addMangaToQueue(categoryId: Long) {
-        val libraryManga = db.getLibraryMangas().executeAsBlocking()
+        val libraryManga = runBlocking { getLibraryManga.await() }
 
         val listToUpdate = if (categoryId != -1L) {
             libraryManga.filter { it.category.toLong() == categoryId }
@@ -323,7 +325,7 @@ class LibraryUpdateService(
                                 }
 
                                 // Don't continue to update if manga not in library
-                                manga.id?.let { getMangaById.await(it) } ?: return@forEach
+                                manga.id?.let { getManga.await(it) } ?: return@forEach
 
                                 withUpdateNotification(
                                     currentlyUpdatingManga,
@@ -434,7 +436,7 @@ class LibraryUpdateService(
             .map { it.toSChapter() }
 
         // Get manga from database to account for if it was removed during the update
-        val dbManga = getMangaById.await(manga.id)
+        val dbManga = getManga.await(manga.id)
             ?: return Pair(emptyList(), emptyList())
 
         // [dbmanga] was used so that manga data doesn't get overwritten
@@ -471,7 +473,14 @@ class LibraryUpdateService(
                                             mangaWithNotif.prepUpdateCover(coverCache, sManga, true)
                                             sManga.thumbnail_url?.let {
                                                 mangaWithNotif.thumbnail_url = it
-                                                db.insertManga(mangaWithNotif).executeAsBlocking()
+                                                try {
+                                                    updateManga.await(
+                                                        mangaWithNotif.toDomainManga()!!
+                                                            .toMangaUpdate(),
+                                                    )
+                                                } catch (e: Exception) {
+                                                    logcat(LogPriority.ERROR) { "Manga don't exist anymore" }
+                                                }
                                             }
                                         } catch (e: Throwable) {
                                             // Ignore errors and continue

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

@@ -11,7 +11,7 @@ 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.interactor.GetManga
 import eu.kanade.domain.manga.model.toDbManga
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.backup.BackupRestoreService
@@ -46,7 +46,7 @@ import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
  */
 class NotificationReceiver : BroadcastReceiver() {
 
-    private val getMangaById: GetMangaById by injectLazy()
+    private val getManga: GetManga by injectLazy()
     private val getChapter: GetChapter by injectLazy()
     private val updateChapter: UpdateChapter by injectLazy()
     private val downloadManager: DownloadManager by injectLazy()
@@ -178,7 +178,7 @@ class NotificationReceiver : BroadcastReceiver() {
      * @param chapterId id of chapter
      */
     private fun openChapter(context: Context, mangaId: Long, chapterId: Long) {
-        val manga = runBlocking { getMangaById.await(mangaId) }
+        val manga = runBlocking { getManga.await(mangaId) }
         val chapter = runBlocking { getChapter.await(chapterId) }
         if (manga != null && chapter != null) {
             val intent = ReaderActivity.newIntent(context, manga.id, chapter.id).apply {
@@ -248,7 +248,7 @@ class NotificationReceiver : BroadcastReceiver() {
                 .map {
                     val chapter = it.copy(read = true)
                     if (preferences.removeAfterMarkedAsRead()) {
-                        val manga = getMangaById.await(mangaId)
+                        val manga = getManga.await(mangaId)
                         if (manga != null) {
                             val source = sourceManager.get(manga.source)
                             if (source != null) {
@@ -270,7 +270,7 @@ class NotificationReceiver : BroadcastReceiver() {
      */
     private fun downloadChapters(chapterUrls: Array<String>, mangaId: Long) {
         launchIO {
-            val manga = getMangaById.await(mangaId)?.toDbManga()
+            val manga = getManga.await(mangaId)?.toDbManga()
             val chapters = chapterUrls.mapNotNull { getChapter.await(it, mangaId)?.toDbChapter() }
             if (manga != null && chapters.isNotEmpty()) {
                 downloadManager.downloadChapters(manga, chapters)

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/data/track/job/DelayedTrackingUpdateJob.kt

@@ -9,7 +9,7 @@ import androidx.work.NetworkType
 import androidx.work.OneTimeWorkRequestBuilder
 import androidx.work.WorkManager
 import androidx.work.WorkerParameters
-import eu.kanade.domain.manga.interactor.GetMangaById
+import eu.kanade.domain.manga.interactor.GetManga
 import eu.kanade.domain.track.interactor.GetTracks
 import eu.kanade.domain.track.interactor.InsertTrack
 import eu.kanade.domain.track.model.toDbTrack
@@ -26,7 +26,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
     CoroutineWorker(context, workerParams) {
 
     override suspend fun doWork(): Result {
-        val getMangaById = Injekt.get<GetMangaById>()
+        val getManga = Injekt.get<GetManga>()
         val getTracks = Injekt.get<GetTracks>()
         val insertTrack = Injekt.get<InsertTrack>()
 
@@ -35,7 +35,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
 
         withContext(Dispatchers.IO) {
             val tracks = delayedTrackingStore.getItems().mapNotNull {
-                val manga = getMangaById.await(it.mangaId) ?: return@withContext
+                val manga = getManga.await(it.mangaId) ?: return@withContext
                 getTracks.await(manga.id)
                     .find { track -> track.id == it.trackId }
                     ?.copy(lastChapterRead = it.lastChapterRead.toDouble())

+ 8 - 4
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt

@@ -6,8 +6,9 @@ import androidx.core.view.isVisible
 import com.bluelinelabs.conductor.Controller
 import com.bluelinelabs.conductor.RouterTransaction
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import eu.kanade.domain.manga.interactor.GetManga
+import eu.kanade.domain.manga.model.toDbManga
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.database.models.toDomainManga
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@@ -18,6 +19,7 @@ import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags
 import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
 import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter
 import eu.kanade.tachiyomi.ui.manga.MangaController
+import kotlinx.coroutines.runBlocking
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 import uy.kohesive.injekt.injectLazy
@@ -27,9 +29,11 @@ class SearchController(
 ) : GlobalSearchController(manga?.title) {
 
     constructor(mangaId: Long) : this(
-        Injekt.get<DatabaseHelper>()
-            .getManga(mangaId)
-            .executeAsBlocking(),
+        runBlocking {
+            Injekt.get<GetManga>()
+                .await(mangaId)
+                ?.toDbManga()
+        },
     )
 
     private var newManga: Manga? = null

+ 28 - 10
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt

@@ -7,11 +7,14 @@ import eu.kanade.domain.category.interactor.SetMangaCategories
 import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
 import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
 import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
+import eu.kanade.domain.manga.interactor.GetManga
+import eu.kanade.domain.manga.interactor.InsertManga
+import eu.kanade.domain.manga.interactor.UpdateManga
 import eu.kanade.domain.manga.model.toDbManga
+import eu.kanade.domain.manga.model.toMangaUpdate
 import eu.kanade.domain.track.interactor.InsertTrack
 import eu.kanade.domain.track.model.toDomainTrack
 import eu.kanade.tachiyomi.data.cache.CoverCache
-import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.database.models.toDomainManga
 import eu.kanade.tachiyomi.data.database.models.toMangaInfo
@@ -67,13 +70,15 @@ open class BrowseSourcePresenter(
     private val sourceId: Long,
     searchQuery: String? = null,
     private val sourceManager: SourceManager = Injekt.get(),
-    private val db: DatabaseHelper = Injekt.get(),
     private val prefs: PreferencesHelper = Injekt.get(),
     private val coverCache: CoverCache = Injekt.get(),
+    private val getManga: GetManga = Injekt.get(),
     private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
     private val getCategories: GetCategories = Injekt.get(),
     private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
     private val setMangaCategories: SetMangaCategories = Injekt.get(),
+    private val insertManga: InsertManga = Injekt.get(),
+    private val updateManga: UpdateManga = Injekt.get(),
     private val insertTrack: InsertTrack = Injekt.get(),
     private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay = Injekt.get(),
 ) : BasePresenter<BrowseSourceController>() {
@@ -208,19 +213,22 @@ open class BrowseSourcePresenter(
      * @return a manga from the database.
      */
     private fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga {
-        var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking()
+        var localManga = runBlocking { getManga.await(sManga.url, sourceId) }
         if (localManga == null) {
             val newManga = Manga.create(sManga.url, sManga.title, sourceId)
             newManga.copyFrom(sManga)
-            val result = db.insertManga(newManga).executeAsBlocking()
-            newManga.id = result.insertedId()
-            localManga = newManga
+            newManga.id = -1
+            val result = runBlocking {
+                val id = insertManga.await(newManga.toDomainManga()!!)
+                getManga.await(id!!)
+            }
+            localManga = result
         } else if (!localManga.favorite) {
             // if the manga isn't a favorite, set its display title from source
             // if it later becomes a favorite, updated title will go to db
-            localManga.title = sManga.title
+            localManga = localManga.copy(title = sManga.title)
         }
-        return localManga
+        return localManga?.toDbManga()!!
     }
 
     /**
@@ -255,7 +263,11 @@ open class BrowseSourcePresenter(
             val networkManga = source.getMangaDetails(manga.toMangaInfo())
             manga.copyFrom(networkManga.toSManga())
             manga.initialized = true
-            db.insertManga(manga).executeAsBlocking()
+            updateManga.await(
+                manga
+                    .toDomainManga()
+                    ?.toMangaUpdate()!!,
+            )
         } catch (e: Exception) {
             logcat(LogPriority.ERROR, e)
         }
@@ -282,7 +294,13 @@ open class BrowseSourcePresenter(
             autoAddTrack(manga)
         }
 
-        db.insertManga(manga).executeAsBlocking()
+        runBlocking {
+            updateManga.await(
+                manga
+                    .toDomainManga()
+                    ?.toMangaUpdate()!!,
+            )
+        }
     }
 
     private fun autoAddTrack(manga: Manga) {

+ 20 - 9
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt

@@ -1,8 +1,13 @@
 package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 
 import android.os.Bundle
-import eu.kanade.tachiyomi.data.database.DatabaseHelper
+import eu.kanade.domain.manga.interactor.GetManga
+import eu.kanade.domain.manga.interactor.InsertManga
+import eu.kanade.domain.manga.interactor.UpdateManga
+import eu.kanade.domain.manga.model.toDbManga
+import eu.kanade.domain.manga.model.toMangaUpdate
 import eu.kanade.tachiyomi.data.database.models.Manga
+import eu.kanade.tachiyomi.data.database.models.toDomainManga
 import eu.kanade.tachiyomi.data.database.models.toMangaInfo
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.extension.ExtensionManager
@@ -16,6 +21,7 @@ import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
 import eu.kanade.tachiyomi.util.lang.runAsObservable
 import eu.kanade.tachiyomi.util.system.logcat
+import kotlinx.coroutines.runBlocking
 import logcat.LogPriority
 import rx.Observable
 import rx.Subscription
@@ -38,8 +44,10 @@ open class GlobalSearchPresenter(
     private val initialQuery: String? = "",
     private val initialExtensionFilter: String? = null,
     val sourceManager: SourceManager = Injekt.get(),
-    val db: DatabaseHelper = Injekt.get(),
     val preferences: PreferencesHelper = Injekt.get(),
+    private val getManga: GetManga = Injekt.get(),
+    private val insertManga: InsertManga = Injekt.get(),
+    private val updateManga: UpdateManga = Injekt.get(),
 ) : BasePresenter<GlobalSearchController>() {
 
     /**
@@ -248,7 +256,7 @@ open class GlobalSearchPresenter(
         val networkManga = source.getMangaDetails(manga.toMangaInfo())
         manga.copyFrom(networkManga.toSManga())
         manga.initialized = true
-        db.insertManga(manga).executeAsBlocking()
+        runBlocking { updateManga.await(manga.toDomainManga()!!.toMangaUpdate()) }
         return manga
     }
 
@@ -260,18 +268,21 @@ open class GlobalSearchPresenter(
      * @return a manga from the database.
      */
     protected open fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga {
-        var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking()
+        var localManga = runBlocking { getManga.await(sManga.url, sourceId) }
         if (localManga == null) {
             val newManga = Manga.create(sManga.url, sManga.title, sourceId)
             newManga.copyFrom(sManga)
-            val result = db.insertManga(newManga).executeAsBlocking()
-            newManga.id = result.insertedId()
-            localManga = newManga
+            newManga.id = -1
+            val result = runBlocking {
+                val id = insertManga.await(newManga.toDomainManga()!!)
+                getManga.await(id!!)
+            }
+            localManga = result
         } else if (!localManga.favorite) {
             // if the manga isn't a favorite, set its display title from source
             // if it later becomes a favorite, updated title will go to db
-            localManga.title = sManga.title
+            localManga = localManga.copy(title = sManga.title)
         }
-        return localManga
+        return localManga!!.toDbManga()
     }
 }

+ 3 - 30
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -11,13 +11,13 @@ import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
 import eu.kanade.domain.chapter.interactor.UpdateChapter
 import eu.kanade.domain.chapter.model.ChapterUpdate
 import eu.kanade.domain.chapter.model.toDbChapter
+import eu.kanade.domain.manga.interactor.GetLibraryManga
 import eu.kanade.domain.manga.interactor.UpdateManga
 import eu.kanade.domain.manga.model.Manga
 import eu.kanade.domain.manga.model.MangaUpdate
 import eu.kanade.domain.track.interactor.GetTracks
 import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.database.models.Chapter
-import eu.kanade.tachiyomi.data.database.models.LibraryManga
 import eu.kanade.tachiyomi.data.download.DownloadManager
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.TrackManager
@@ -60,6 +60,7 @@ typealias LibraryMap = Map<Long, List<LibraryItem>>
  */
 class LibraryPresenter(
     private val handler: DatabaseHandler = Injekt.get(),
+    private val getLibraryManga: GetLibraryManga = Injekt.get(),
     private val getTracks: GetTracks = Injekt.get(),
     private val getCategories: GetCategories = Injekt.get(),
     private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
@@ -410,35 +411,7 @@ class LibraryPresenter(
         val defaultLibraryDisplayMode = preferences.libraryDisplayMode()
         val shouldSetFromCategory = preferences.categorizedDisplaySettings()
 
-        // TODO: Move this to domain/data layer
-        return handler
-            .subscribeToList {
-                mangasQueries.getLibrary { _id: Long, source: Long, url: String, artist: String?, author: String?, description: String?, genre: List<String>?, title: String, status: Long, thumbnail_url: String?, favorite: Boolean, last_update: Long?, next_update: Long?, initialized: Boolean, viewer: Long, chapter_flags: Long, cover_last_modified: Long, date_added: Long, unread_count: Long, read_count: Long, category: Long ->
-                    LibraryManga().apply {
-                        this.id = _id
-                        this.source = source
-                        this.url = url
-                        this.artist = artist
-                        this.author = author
-                        this.description = description
-                        this.genre = genre?.joinToString()
-                        this.title = title
-                        this.status = status.toInt()
-                        this.thumbnail_url = thumbnail_url
-                        this.favorite = favorite
-                        this.last_update = last_update ?: 0
-                        this.initialized = initialized
-                        this.viewer_flags = viewer.toInt()
-                        this.chapter_flags = chapter_flags.toInt()
-                        this.cover_last_modified = cover_last_modified
-                        this.date_added = date_added
-                        this.unreadCount = unread_count.toInt()
-                        this.readCount = read_count.toInt()
-                        this.category = category.toInt()
-                    }
-                }
-            }
-            .asObservable()
+        return getLibraryManga.subscribe().asObservable()
             .map { list ->
                 list.map { libraryManga ->
                     // Display mode based on user preference: take it from global library setting or category

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt

@@ -149,7 +149,7 @@ class MangaPresenter(
 
         presenterScope.launchIO {
             if (!getMangaAndChapters.awaitManga(mangaId).favorite) {
-                ChapterSettingsHelper.applySettingDefaults(mangaId, setMangaChapterFlags)
+                ChapterSettingsHelper.applySettingDefaults(mangaId)
             }
 
             getMangaAndChapters.subscribe(mangaId)

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFullCoverDialog.kt

@@ -20,7 +20,7 @@ import androidx.core.os.bundleOf
 import coil.imageLoader
 import coil.request.ImageRequest
 import coil.size.Size
-import eu.kanade.domain.manga.interactor.GetMangaById
+import eu.kanade.domain.manga.interactor.GetManga
 import eu.kanade.domain.manga.interactor.UpdateManga
 import eu.kanade.domain.manga.model.Manga
 import eu.kanade.domain.manga.model.hasCustomCover
@@ -161,7 +161,7 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
 
     inner class MangaFullCoverPresenter(
         private val mangaId: Long,
-        private val getMangaById: GetMangaById = Injekt.get(),
+        private val getManga: GetManga = Injekt.get(),
     ) : Presenter<MangaFullCoverDialog>() {
 
         private var presenterScope: CoroutineScope = MainScope()
@@ -176,7 +176,7 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
         override fun onCreate(savedState: Bundle?) {
             super.onCreate(savedState)
             presenterScope.launchIO {
-                getMangaById.subscribe(mangaId)
+                getManga.subscribe(mangaId)
                     .collect { _mangaFlow.value = it }
             }
         }

+ 11 - 7
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt

@@ -11,13 +11,13 @@ import eu.kanade.domain.chapter.model.ChapterUpdate
 import eu.kanade.domain.chapter.model.toDbChapter
 import eu.kanade.domain.history.interactor.UpsertHistory
 import eu.kanade.domain.history.model.HistoryUpdate
-import eu.kanade.domain.manga.interactor.GetMangaById
+import eu.kanade.domain.manga.interactor.GetManga
+import eu.kanade.domain.manga.interactor.SetMangaViewerFlags
 import eu.kanade.domain.manga.model.isLocal
 import eu.kanade.domain.manga.model.toDbManga
 import eu.kanade.domain.track.interactor.GetTracks
 import eu.kanade.domain.track.interactor.InsertTrack
 import eu.kanade.domain.track.model.toDbTrack
-import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.database.models.toDomainManga
 import eu.kanade.tachiyomi.data.download.DownloadManager
@@ -68,17 +68,17 @@ import java.util.concurrent.TimeUnit
  * Presenter used by the activity to perform background operations.
  */
 class ReaderPresenter(
-    private val db: DatabaseHelper = Injekt.get(),
     private val sourceManager: SourceManager = Injekt.get(),
     private val downloadManager: DownloadManager = Injekt.get(),
     private val preferences: PreferencesHelper = Injekt.get(),
     private val delayedTrackingStore: DelayedTrackingStore = Injekt.get(),
-    private val getMangaById: GetMangaById = Injekt.get(),
+    private val getManga: GetManga = Injekt.get(),
     private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
     private val getTracks: GetTracks = Injekt.get(),
     private val insertTrack: InsertTrack = Injekt.get(),
     private val upsertHistory: UpsertHistory = Injekt.get(),
     private val updateChapter: UpdateChapter = Injekt.get(),
+    private val setMangaViewerFlags: SetMangaViewerFlags = Injekt.get(),
 ) : BasePresenter<ReaderActivity>() {
 
     /**
@@ -242,7 +242,7 @@ class ReaderPresenter(
 
         launchIO {
             try {
-                val manga = getMangaById.await(mangaId)
+                val manga = getManga.await(mangaId)
                 withUIContext {
                     manga?.let { init(it.toDbManga(), initialChapterId) }
                 }
@@ -570,7 +570,9 @@ class ReaderPresenter(
     fun setMangaReadingMode(readingModeType: Int) {
         val manga = manga ?: return
         manga.readingModeType = readingModeType
-        db.updateViewerFlags(manga).executeAsBlocking()
+        runBlocking {
+            setMangaViewerFlags.awaitSetMangaReadingMode(manga.id!!.toLong(), readingModeType.toLong())
+        }
 
         Observable.timer(250, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
             .subscribeFirst({ view, _ ->
@@ -605,7 +607,9 @@ class ReaderPresenter(
     fun setMangaOrientationType(rotationType: Int) {
         val manga = manga ?: return
         manga.orientationType = rotationType
-        db.updateViewerFlags(manga).executeAsBlocking()
+        runBlocking {
+            setMangaViewerFlags.awaitSetOrientationType(manga.id!!.toLong(), rotationType.toLong())
+        }
 
         logcat(LogPriority.INFO) { "Manga orientation is ${manga.orientationType}" }
 

+ 24 - 25
app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt

@@ -1,7 +1,7 @@
 package eu.kanade.tachiyomi.util.chapter
 
+import eu.kanade.domain.manga.interactor.GetFavorites
 import eu.kanade.domain.manga.interactor.SetMangaChapterFlags
-import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.util.lang.launchIO
@@ -10,7 +10,8 @@ import uy.kohesive.injekt.injectLazy
 object ChapterSettingsHelper {
 
     private val prefs: PreferencesHelper by injectLazy()
-    private val db: DatabaseHelper by injectLazy()
+    private val getFavorites: GetFavorites by injectLazy()
+    private val setMangaChapterFlags: SetMangaChapterFlags by injectLazy()
 
     /**
      * Updates the global Chapter Settings in Preferences.
@@ -23,19 +24,20 @@ object ChapterSettingsHelper {
      * Updates a single manga's Chapter Settings to match what's set in Preferences.
      */
     fun applySettingDefaults(manga: Manga) {
-        with(manga) {
-            readFilter = prefs.filterChapterByRead()
-            downloadedFilter = prefs.filterChapterByDownloaded()
-            bookmarkedFilter = prefs.filterChapterByBookmarked()
-            sorting = prefs.sortChapterBySourceOrNumber()
-            displayMode = prefs.displayChapterByNameOrNumber()
-            setChapterOrder(prefs.sortChapterByAscendingOrDescending())
+        launchIO {
+            setMangaChapterFlags.awaitSetAllFlags(
+                mangaId = manga.id!!,
+                unreadFilter = prefs.filterChapterByRead().toLong(),
+                downloadedFilter = prefs.filterChapterByDownloaded().toLong(),
+                bookmarkedFilter = prefs.filterChapterByBookmarked().toLong(),
+                sortingMode = prefs.sortChapterBySourceOrNumber().toLong(),
+                sortingDirection = prefs.sortChapterByAscendingOrDescending().toLong(),
+                displayMode = prefs.displayChapterByNameOrNumber().toLong(),
+            )
         }
-
-        db.updateChapterFlags(manga).executeAsBlocking()
     }
 
-    suspend fun applySettingDefaults(mangaId: Long, setMangaChapterFlags: SetMangaChapterFlags) {
+    suspend fun applySettingDefaults(mangaId: Long) {
         setMangaChapterFlags.awaitSetAllFlags(
             mangaId = mangaId,
             unreadFilter = prefs.filterChapterByRead().toLong(),
@@ -52,21 +54,18 @@ object ChapterSettingsHelper {
      */
     fun updateAllMangasWithGlobalDefaults() {
         launchIO {
-            val updatedMangas = db.getFavoriteMangas()
-                .executeAsBlocking()
+            getFavorites.await()
                 .map { manga ->
-                    with(manga) {
-                        readFilter = prefs.filterChapterByRead()
-                        downloadedFilter = prefs.filterChapterByDownloaded()
-                        bookmarkedFilter = prefs.filterChapterByBookmarked()
-                        sorting = prefs.sortChapterBySourceOrNumber()
-                        displayMode = prefs.displayChapterByNameOrNumber()
-                        setChapterOrder(prefs.sortChapterByAscendingOrDescending())
-                    }
-                    manga
+                    setMangaChapterFlags.awaitSetAllFlags(
+                        mangaId = manga.id,
+                        unreadFilter = prefs.filterChapterByRead().toLong(),
+                        downloadedFilter = prefs.filterChapterByDownloaded().toLong(),
+                        bookmarkedFilter = prefs.filterChapterByBookmarked().toLong(),
+                        sortingMode = prefs.sortChapterBySourceOrNumber().toLong(),
+                        sortingDirection = prefs.sortChapterByAscendingOrDescending().toLong(),
+                        displayMode = prefs.displayChapterByNameOrNumber().toLong(),
+                    )
                 }
-
-            db.updateChapterFlags(updatedMangas).executeAsBlocking()
         }
     }
 }

+ 38 - 0
app/src/main/sqldelight/data/mangas.sq

@@ -145,6 +145,44 @@ deleteMangasNotInLibraryBySourceIds:
 DELETE FROM mangas
 WHERE favorite = 0 AND source IN :sourceIds;
 
+INSERT INTO mangas(
+    source,
+    url,
+    artist,
+    author,
+    description,
+    genre,
+    title,
+    status,
+    thumbnail_url,
+    favorite,
+    last_update,
+    next_update,
+    initialized,
+    viewer,
+    chapter_flags,
+    cover_last_modified,
+    date_added
+) VALUES (
+    :source,
+    :url,
+    :artist,
+    :author,
+    :description,
+    :genre,
+    :title,
+    :status,
+    :thumbnailUrl,
+    :favorite,
+    :lastUpdate,
+    0,
+    :initialized,
+    :viewerFlags,
+    :chapterFlags,
+    :coverLastModified,
+    :dateAdded
+);
+
 update:
 UPDATE mangas SET
     source = coalesce(:source, source),