Browse Source

Migrate things to use newer data models (#9239)

* Remove old database models from Coil

* Remove old database models from TrackInfoDialogHome

* Remove old database models from Backup Manager
Andreas 2 years ago
parent
commit
dfdb688b43

+ 11 - 0
app/src/main/java/eu/kanade/domain/chapter/model/Chapter.kt

@@ -2,6 +2,7 @@ package eu.kanade.domain.chapter.model
 
 import eu.kanade.tachiyomi.data.database.models.ChapterImpl
 import eu.kanade.tachiyomi.source.model.SChapter
+import tachiyomi.data.Chapters
 import tachiyomi.domain.chapter.model.Chapter
 import eu.kanade.tachiyomi.data.database.models.Chapter as DbChapter
 
@@ -26,6 +27,16 @@ fun Chapter.copyFromSChapter(sChapter: SChapter): Chapter {
     )
 }
 
+fun Chapter.copyFrom(other: Chapters): Chapter {
+    return copy(
+        name = other.name,
+        url = other.url,
+        dateUpload = other.date_upload,
+        chapterNumber = other.chapter_number,
+        scanlator = other.scanlator?.ifBlank { null },
+    )
+}
+
 fun Chapter.toDbChapter(): DbChapter = ChapterImpl().also {
     it.id = id
     it.manga_id = mangaId

+ 9 - 8
app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogHome.kt

@@ -43,6 +43,7 @@ import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
+import eu.kanade.domain.track.model.toDbTrack
 import eu.kanade.presentation.components.DropdownMenu
 import eu.kanade.presentation.track.components.TrackLogoIcon
 import eu.kanade.tachiyomi.R
@@ -84,10 +85,10 @@ fun TrackInfoDialogHome(
                 TrackInfoItem(
                     title = item.track.title,
                     service = item.service,
-                    status = item.service.getStatus(item.track.status),
+                    status = item.service.getStatus(item.track.status.toInt()),
                     onStatusClick = { onStatusClick(item) },
-                    chapters = "${item.track.last_chapter_read.toInt()}".let {
-                        val totalChapters = item.track.total_chapters
+                    chapters = "${item.track.lastChapterRead.toInt()}".let {
+                        val totalChapters = item.track.totalChapters
                         if (totalChapters > 0) {
                             // Add known total chapter count
                             "$it / $totalChapters"
@@ -96,16 +97,16 @@ fun TrackInfoDialogHome(
                         }
                     },
                     onChaptersClick = { onChapterClick(item) },
-                    score = item.service.displayScore(item.track)
+                    score = item.service.displayScore(item.track.toDbTrack())
                         .takeIf { supportsScoring && item.track.score != 0F },
                     onScoreClick = { onScoreClick(item) }
                         .takeIf { supportsScoring },
-                    startDate = remember(item.track.started_reading_date) { dateFormat.format(item.track.started_reading_date) }
-                        .takeIf { supportsReadingDates && item.track.started_reading_date != 0L },
+                    startDate = remember(item.track.startDate) { dateFormat.format(item.track.startDate) }
+                        .takeIf { supportsReadingDates && item.track.startDate != 0L },
                     onStartDateClick = { onStartDateEdit(item) } // TODO
                         .takeIf { supportsReadingDates },
-                    endDate = dateFormat.format(item.track.finished_reading_date)
-                        .takeIf { supportsReadingDates && item.track.finished_reading_date != 0L },
+                    endDate = dateFormat.format(item.track.finishDate)
+                        .takeIf { supportsReadingDates && item.track.finishDate != 0L },
                     onEndDateClick = { onEndDateEdit(item) }
                         .takeIf { supportsReadingDates },
                     onNewSearch = { onNewSearch(item) },

+ 1 - 4
app/src/main/java/eu/kanade/tachiyomi/App.kt

@@ -28,7 +28,6 @@ import eu.kanade.domain.ui.UiPreferences
 import eu.kanade.domain.ui.model.setAppCompatDelegateThemeMode
 import eu.kanade.tachiyomi.crash.CrashActivity
 import eu.kanade.tachiyomi.crash.GlobalExceptionHandler
-import eu.kanade.tachiyomi.data.coil.DomainMangaKeyer
 import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
 import eu.kanade.tachiyomi.data.coil.MangaCoverKeyer
 import eu.kanade.tachiyomi.data.coil.MangaKeyer
@@ -143,11 +142,9 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
                     add(GifDecoder.Factory())
                 }
                 add(TachiyomiImageDecoder.Factory())
-                add(MangaCoverFetcher.Factory(lazy(callFactoryInit), lazy(diskCacheInit)))
-                add(MangaCoverFetcher.DomainMangaFactory(lazy(callFactoryInit), lazy(diskCacheInit)))
+                add(MangaCoverFetcher.MangaFactory(lazy(callFactoryInit), lazy(diskCacheInit)))
                 add(MangaCoverFetcher.MangaCoverFactory(lazy(callFactoryInit), lazy(diskCacheInit)))
                 add(MangaKeyer())
-                add(DomainMangaKeyer())
                 add(MangaCoverKeyer())
             }
             callFactory(callFactoryInit)

+ 85 - 86
app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt

@@ -4,6 +4,8 @@ import android.Manifest
 import android.content.Context
 import android.net.Uri
 import com.hippo.unifile.UniFile
+import eu.kanade.domain.chapter.model.copyFrom
+import eu.kanade.domain.manga.model.copyFrom
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY
 import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY_MASK
@@ -22,9 +24,6 @@ import eu.kanade.tachiyomi.data.backup.models.BackupSource
 import eu.kanade.tachiyomi.data.backup.models.backupCategoryMapper
 import eu.kanade.tachiyomi.data.backup.models.backupChapterMapper
 import eu.kanade.tachiyomi.data.backup.models.backupTrackMapper
-import eu.kanade.tachiyomi.data.database.models.Chapter
-import eu.kanade.tachiyomi.data.database.models.Manga
-import eu.kanade.tachiyomi.data.database.models.Track
 import eu.kanade.tachiyomi.source.model.copyFrom
 import eu.kanade.tachiyomi.util.system.hasPermission
 import kotlinx.serialization.protobuf.ProtoBuf
@@ -44,13 +43,13 @@ import tachiyomi.domain.category.model.Category
 import tachiyomi.domain.history.model.HistoryUpdate
 import tachiyomi.domain.library.service.LibraryPreferences
 import tachiyomi.domain.manga.interactor.GetFavorites
+import tachiyomi.domain.manga.model.Manga
 import tachiyomi.domain.source.service.SourceManager
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 import java.io.FileOutputStream
 import java.util.Date
 import kotlin.math.max
-import tachiyomi.domain.manga.model.Manga as DomainManga
 
 class BackupManager(
     private val context: Context,
@@ -136,12 +135,12 @@ class BackupManager(
         }
     }
 
-    private fun backupExtensionInfo(mangas: List<DomainManga>): List<BackupSource> {
+    private fun backupExtensionInfo(mangas: List<Manga>): List<BackupSource> {
         return mangas
             .asSequence()
-            .map { it.source }
+            .map(Manga::source)
             .distinct()
-            .map { sourceManager.getOrStub(it) }
+            .map(sourceManager::getOrStub)
             .map { BackupSource.copyFrom(it) }
             .toList()
     }
@@ -162,7 +161,7 @@ class BackupManager(
         }
     }
 
-    private suspend fun backupMangas(mangas: List<DomainManga>, flags: Int): List<BackupManga> {
+    private suspend fun backupMangas(mangas: List<Manga>, flags: Int): List<BackupManga> {
         return mangas.map {
             backupManga(it, flags)
         }
@@ -175,7 +174,7 @@ class BackupManager(
      * @param options options for the backup
      * @return [BackupManga] containing manga in a serializable form
      */
-    private suspend fun backupManga(manga: DomainManga, options: Int): BackupManga {
+    private suspend fun backupManga(manga: Manga, options: Int): BackupManga {
         // Entry for this manga
         val mangaObject = BackupManga.copyFrom(manga)
 
@@ -222,10 +221,11 @@ class BackupManager(
         return mangaObject
     }
 
-    internal suspend fun restoreExistingManga(manga: Manga, dbManga: Mangas) {
-        manga.id = dbManga._id
-        manga.copyFrom(dbManga)
+    internal suspend fun restoreExistingManga(manga: Manga, dbManga: Mangas): Manga {
+        var manga = manga.copy(id = dbManga._id)
+        manga = manga.copyFrom(dbManga)
         updateManga(manga)
+        return manga
     }
 
     /**
@@ -235,10 +235,10 @@ class BackupManager(
      * @return Updated manga info.
      */
     internal suspend fun restoreNewManga(manga: Manga): Manga {
-        return manga.also {
-            it.initialized = it.description != null
-            it.id = insertManga(it)
-        }
+        return manga.copy(
+            initialized = manga.description != null,
+            id = insertManga(manga),
+        )
     }
 
     /**
@@ -369,28 +369,28 @@ class BackupManager(
      * @param manga the manga whose sync have to be restored.
      * @param tracks the track list to restore.
      */
-    internal suspend fun restoreTracking(manga: Manga, tracks: List<Track>) {
+    internal suspend fun restoreTracking(manga: Manga, tracks: List<tachiyomi.domain.track.model.Track>) {
         // Fix foreign keys with the current manga id
-        tracks.map { it.manga_id = manga.id!! }
+        val tracks = tracks.map { it.copy(mangaId = manga.id!!) }
 
         // Get tracks from database
         val dbTracks = handler.awaitList { manga_syncQueries.getTracksByMangaId(manga.id!!) }
         val toUpdate = mutableListOf<Manga_sync>()
-        val toInsert = mutableListOf<Track>()
+        val toInsert = mutableListOf<tachiyomi.domain.track.model.Track>()
 
         tracks.forEach { track ->
             var isInDatabase = false
             for (dbTrack in dbTracks) {
-                if (track.sync_id == dbTrack.sync_id.toInt()) {
+                if (track.syncId == dbTrack.sync_id) {
                     // The sync is already in the db, only update its fields
                     var temp = dbTrack
-                    if (track.media_id != dbTrack.remote_id) {
-                        temp = temp.copy(remote_id = track.media_id)
+                    if (track.remoteId != dbTrack.remote_id) {
+                        temp = temp.copy(remote_id = track.remoteId)
                     }
-                    if (track.library_id != dbTrack.library_id) {
-                        temp = temp.copy(library_id = track.library_id)
+                    if (track.libraryId != dbTrack.library_id) {
+                        temp = temp.copy(library_id = track.libraryId)
                     }
-                    temp = temp.copy(last_chapter_read = max(dbTrack.last_chapter_read, track.last_chapter_read.toDouble()))
+                    temp = temp.copy(last_chapter_read = max(dbTrack.last_chapter_read, track.lastChapterRead))
                     isInDatabase = true
                     toUpdate.add(temp)
                     break
@@ -398,8 +398,7 @@ class BackupManager(
             }
             if (!isInDatabase) {
                 // Insert new sync. Let the db assign the id
-                track.id = null
-                toInsert.add(track)
+                toInsert.add(track.copy(id = 0))
             }
         }
         // Update database
@@ -428,47 +427,47 @@ class BackupManager(
             handler.await(true) {
                 toInsert.forEach { track ->
                     manga_syncQueries.insert(
-                        track.manga_id,
-                        track.sync_id.toLong(),
-                        track.media_id,
-                        track.library_id,
+                        track.mangaId,
+                        track.syncId,
+                        track.remoteId,
+                        track.libraryId,
                         track.title,
-                        track.last_chapter_read.toDouble(),
-                        track.total_chapters.toLong(),
-                        track.status.toLong(),
+                        track.lastChapterRead,
+                        track.totalChapters,
+                        track.status,
                         track.score,
-                        track.tracking_url,
-                        track.started_reading_date,
-                        track.finished_reading_date,
+                        track.remoteUrl,
+                        track.startDate,
+                        track.finishDate,
                     )
                 }
             }
         }
     }
 
-    internal suspend fun restoreChapters(manga: Manga, chapters: List<Chapter>) {
+    internal suspend fun restoreChapters(manga: Manga, chapters: List<tachiyomi.domain.chapter.model.Chapter>) {
         val dbChapters = handler.awaitList { chaptersQueries.getChaptersByMangaId(manga.id!!) }
 
-        chapters.forEach { chapter ->
+        val processed = chapters.map { chapter ->
+            var chapter = chapter
             val dbChapter = dbChapters.find { it.url == chapter.url }
             if (dbChapter != null) {
-                chapter.id = dbChapter._id
-                chapter.copyFrom(dbChapter)
+                chapter = chapter.copy(id = dbChapter._id)
+                chapter = chapter.copyFrom(dbChapter)
                 if (dbChapter.read && !chapter.read) {
-                    chapter.read = dbChapter.read
-                    chapter.last_page_read = dbChapter.last_page_read.toInt()
-                } else if (chapter.last_page_read == 0 && dbChapter.last_page_read != 0L) {
-                    chapter.last_page_read = dbChapter.last_page_read.toInt()
+                    chapter = chapter.copy(read = dbChapter.read, lastPageRead = dbChapter.last_page_read)
+                } else if (chapter.lastPageRead == 0L && dbChapter.last_page_read != 0L) {
+                    chapter = chapter.copy(lastPageRead = dbChapter.last_page_read)
                 }
                 if (!chapter.bookmark && dbChapter.bookmark) {
-                    chapter.bookmark = dbChapter.bookmark
+                    chapter = chapter.copy(bookmark = dbChapter.bookmark)
                 }
             }
 
-            chapter.manga_id = manga.id
+            chapter.copy(mangaId = manga.id ?: -1)
         }
 
-        val newChapters = chapters.groupBy { it.id != null }
+        val newChapters = processed.groupBy { it.id > 0 }
         newChapters[true]?.let { updateKnownChapters(it) }
         newChapters[false]?.let { insertChapters(it) }
     }
@@ -495,19 +494,19 @@ class BackupManager(
                 artist = manga.artist,
                 author = manga.author,
                 description = manga.description,
-                genre = manga.getGenres(),
+                genre = manga.genre,
                 title = manga.title,
-                status = manga.status.toLong(),
-                thumbnailUrl = manga.thumbnail_url,
+                status = manga.status,
+                thumbnailUrl = manga.thumbnailUrl,
                 favorite = manga.favorite,
-                lastUpdate = manga.last_update,
+                lastUpdate = manga.lastUpdate,
                 nextUpdate = 0L,
                 initialized = manga.initialized,
-                viewerFlags = manga.viewer_flags.toLong(),
-                chapterFlags = manga.chapter_flags.toLong(),
-                coverLastModified = manga.cover_last_modified,
-                dateAdded = manga.date_added,
-                updateStrategy = manga.update_strategy,
+                viewerFlags = manga.viewerFlags,
+                chapterFlags = manga.chapterFlags,
+                coverLastModified = manga.coverLastModified,
+                dateAdded = manga.dateAdded,
+                updateStrategy = manga.updateStrategy,
             )
             mangasQueries.selectLastInsertedRowId()
         }
@@ -521,42 +520,42 @@ class BackupManager(
                 artist = manga.artist,
                 author = manga.author,
                 description = manga.description,
-                genre = manga.genre,
+                genre = manga.genre?.joinToString(separator = ", "),
                 title = manga.title,
-                status = manga.status.toLong(),
-                thumbnailUrl = manga.thumbnail_url,
+                status = manga.status,
+                thumbnailUrl = manga.thumbnailUrl,
                 favorite = manga.favorite.toLong(),
-                lastUpdate = manga.last_update,
+                lastUpdate = manga.lastUpdate,
                 initialized = manga.initialized.toLong(),
-                viewer = manga.viewer_flags.toLong(),
-                chapterFlags = manga.chapter_flags.toLong(),
-                coverLastModified = manga.cover_last_modified,
-                dateAdded = manga.date_added,
-                mangaId = manga.id!!,
-                updateStrategy = manga.update_strategy.let(updateStrategyAdapter::encode),
+                viewer = manga.viewerFlags,
+                chapterFlags = manga.chapterFlags,
+                coverLastModified = manga.coverLastModified,
+                dateAdded = manga.dateAdded,
+                mangaId = manga.id,
+                updateStrategy = manga.updateStrategy.let(updateStrategyAdapter::encode),
             )
         }
-        return manga.id!!
+        return manga.id
     }
 
     /**
      * Inserts list of chapters
      */
-    private suspend fun insertChapters(chapters: List<Chapter>) {
+    private suspend fun insertChapters(chapters: List<tachiyomi.domain.chapter.model.Chapter>) {
         handler.await(true) {
             chapters.forEach { chapter ->
                 chaptersQueries.insert(
-                    chapter.manga_id!!,
+                    chapter.mangaId,
                     chapter.url,
                     chapter.name,
                     chapter.scanlator,
                     chapter.read,
                     chapter.bookmark,
-                    chapter.last_page_read.toLong(),
-                    chapter.chapter_number,
-                    chapter.source_order.toLong(),
-                    chapter.date_fetch,
-                    chapter.date_upload,
+                    chapter.lastPageRead,
+                    chapter.chapterNumber,
+                    chapter.sourceOrder,
+                    chapter.dateFetch,
+                    chapter.dateUpload,
                 )
             }
         }
@@ -565,22 +564,22 @@ class BackupManager(
     /**
      * Updates a list of chapters
      */
-    private suspend fun updateChapters(chapters: List<Chapter>) {
+    private suspend fun updateChapters(chapters: List<tachiyomi.domain.chapter.model.Chapter>) {
         handler.await(true) {
             chapters.forEach { chapter ->
                 chaptersQueries.update(
-                    chapter.manga_id!!,
+                    chapter.mangaId,
                     chapter.url,
                     chapter.name,
                     chapter.scanlator,
                     chapter.read.toLong(),
                     chapter.bookmark.toLong(),
-                    chapter.last_page_read.toLong(),
-                    chapter.chapter_number.toDouble(),
-                    chapter.source_order.toLong(),
-                    chapter.date_fetch,
-                    chapter.date_upload,
-                    chapter.id!!,
+                    chapter.lastPageRead,
+                    chapter.chapterNumber.toDouble(),
+                    chapter.sourceOrder,
+                    chapter.dateFetch,
+                    chapter.dateUpload,
+                    chapter.id,
                 )
             }
         }
@@ -589,7 +588,7 @@ class BackupManager(
     /**
      * Updates a list of chapters with known database ids
      */
-    private suspend fun updateKnownChapters(chapters: List<Chapter>) {
+    private suspend fun updateKnownChapters(chapters: List<tachiyomi.domain.chapter.model.Chapter>) {
         handler.await(true) {
             chapters.forEach { chapter ->
                 chaptersQueries.update(
@@ -599,12 +598,12 @@ class BackupManager(
                     scanlator = null,
                     read = chapter.read.toLong(),
                     bookmark = chapter.bookmark.toLong(),
-                    lastPageRead = chapter.last_page_read.toLong(),
+                    lastPageRead = chapter.lastPageRead,
                     chapterNumber = null,
                     sourceOrder = null,
                     dateFetch = null,
                     dateUpload = null,
-                    chapterId = chapter.id!!,
+                    chapterId = chapter.id,
                 )
             }
         }

+ 4 - 6
app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt

@@ -7,13 +7,13 @@ import eu.kanade.tachiyomi.data.backup.models.BackupCategory
 import eu.kanade.tachiyomi.data.backup.models.BackupHistory
 import eu.kanade.tachiyomi.data.backup.models.BackupManga
 import eu.kanade.tachiyomi.data.backup.models.BackupSource
-import eu.kanade.tachiyomi.data.database.models.Chapter
-import eu.kanade.tachiyomi.data.database.models.Manga
-import eu.kanade.tachiyomi.data.database.models.Track
 import eu.kanade.tachiyomi.util.BackupUtil
 import eu.kanade.tachiyomi.util.system.createFileInCacheDir
 import kotlinx.coroutines.Job
 import okio.source
+import tachiyomi.domain.chapter.model.Chapter
+import tachiyomi.domain.manga.model.Manga
+import tachiyomi.domain.track.model.Track
 import java.io.File
 import java.text.SimpleDateFormat
 import java.util.Date
@@ -127,7 +127,7 @@ class BackupRestorer(
             } else {
                 // Manga in database
                 // Copy information from manga already in database
-                backupManager.restoreExistingManga(manga, dbManga)
+                val manga = backupManager.restoreExistingManga(manga, dbManga)
                 // Fetch rest of manga information
                 restoreNewManga(manga, chapters, categories, history, tracks, backupCategories)
             }
@@ -156,8 +156,6 @@ class BackupRestorer(
         backupCategories: List<BackupCategory>,
     ) {
         val fetchedManga = backupManager.restoreNewManga(manga)
-        fetchedManga.id ?: return
-
         backupManager.restoreChapters(fetchedManga, chapters)
         restoreExtras(fetchedManga, categories, history, tracks, backupCategories)
     }

+ 14 - 14
app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupChapter.kt

@@ -1,8 +1,8 @@
 package eu.kanade.tachiyomi.data.backup.models
 
-import eu.kanade.tachiyomi.data.database.models.ChapterImpl
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.protobuf.ProtoNumber
+import tachiyomi.domain.chapter.model.Chapter
 
 @Serializable
 data class BackupChapter(
@@ -21,19 +21,19 @@ data class BackupChapter(
     @ProtoNumber(9) var chapterNumber: Float = 0F,
     @ProtoNumber(10) var sourceOrder: Long = 0,
 ) {
-    fun toChapterImpl(): ChapterImpl {
-        return ChapterImpl().apply {
-            url = [email protected]
-            name = [email protected]
-            chapter_number = [email protected]
-            scanlator = [email protected]
-            read = [email protected]
-            bookmark = [email protected]
-            last_page_read = [email protected]()
-            date_fetch = [email protected]
-            date_upload = [email protected]
-            source_order = [email protected]()
-        }
+    fun toChapterImpl(): Chapter {
+        return Chapter.create().copy(
+            url = [email protected],
+            name = [email protected],
+            chapterNumber = [email protected],
+            scanlator = [email protected],
+            read = [email protected],
+            bookmark = [email protected],
+            lastPageRead = [email protected],
+            dateFetch = [email protected],
+            dateUpload = [email protected],
+            sourceOrder = [email protected],
+        )
     }
 }
 

+ 21 - 22
app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupManga.kt

@@ -1,13 +1,12 @@
 package eu.kanade.tachiyomi.data.backup.models
 
-import eu.kanade.tachiyomi.data.database.models.ChapterImpl
-import eu.kanade.tachiyomi.data.database.models.MangaImpl
-import eu.kanade.tachiyomi.data.database.models.TrackImpl
 import eu.kanade.tachiyomi.source.model.UpdateStrategy
 import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.protobuf.ProtoNumber
+import tachiyomi.domain.chapter.model.Chapter
 import tachiyomi.domain.manga.model.Manga
+import tachiyomi.domain.track.model.Track
 
 @Suppress("DEPRECATION")
 @Serializable
@@ -41,32 +40,32 @@ data class BackupManga(
     @ProtoNumber(104) var history: List<BackupHistory> = emptyList(),
     @ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
 ) {
-    fun getMangaImpl(): MangaImpl {
-        return MangaImpl().apply {
-            url = [email protected]
-            title = [email protected]
-            artist = [email protected]
-            author = [email protected]
-            description = [email protected]
-            genre = [email protected].joinToString()
-            status = [email protected]
-            thumbnail_url = [email protected]
-            favorite = [email protected]
-            source = [email protected]
-            date_added = [email protected]
-            viewer_flags = [email protected]_flags ?: [email protected]
-            chapter_flags = [email protected]
-            update_strategy = [email protected]
-        }
+    fun getMangaImpl(): Manga {
+        return Manga.create().copy(
+            url = [email protected],
+            title = [email protected],
+            artist = [email protected],
+            author = [email protected],
+            description = [email protected],
+            genre = [email protected],
+            status = [email protected].toLong(),
+            thumbnailUrl = [email protected],
+            favorite = [email protected],
+            source = [email protected],
+            dateAdded = [email protected],
+            viewerFlags = ([email protected]_flags ?: [email protected]).toLong(),
+            chapterFlags = [email protected](),
+            updateStrategy = [email protected],
+        )
     }
 
-    fun getChaptersImpl(): List<ChapterImpl> {
+    fun getChaptersImpl(): List<Chapter> {
         return chapters.map {
             it.toChapterImpl()
         }
     }
 
-    fun getTrackingImpl(): List<TrackImpl> {
+    fun getTrackingImpl(): List<Track> {
         return tracking.map {
             it.getTrackingImpl()
         }

+ 18 - 17
app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupTracking.kt

@@ -1,8 +1,8 @@
 package eu.kanade.tachiyomi.data.backup.models
 
-import eu.kanade.tachiyomi.data.database.models.TrackImpl
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.protobuf.ProtoNumber
+import tachiyomi.domain.track.model.Track
 
 @Serializable
 data class BackupTracking(
@@ -29,25 +29,26 @@ data class BackupTracking(
     @ProtoNumber(100) var mediaId: Long = 0,
 ) {
 
-    fun getTrackingImpl(): TrackImpl {
-        return TrackImpl().apply {
-            sync_id = [email protected]
-            @Suppress("DEPRECATION")
-            media_id = if ([email protected] != 0) {
+    fun getTrackingImpl(): Track {
+        return Track(
+            id = -1,
+            mangaId = -1,
+            syncId = [email protected](),
+            remoteId = if ([email protected] != 0) {
                 [email protected]()
             } else {
                 [email protected]
-            }
-            library_id = [email protected]
-            title = [email protected]
-            last_chapter_read = [email protected]
-            total_chapters = [email protected]
-            score = [email protected]
-            status = [email protected]
-            started_reading_date = [email protected]
-            finished_reading_date = [email protected]
-            tracking_url = [email protected]
-        }
+            },
+            libraryId = [email protected],
+            title = [email protected],
+            lastChapterRead = [email protected](),
+            totalChapters = [email protected](),
+            score = [email protected],
+            status = [email protected].toLong(),
+            startDate = [email protected],
+            finishDate = [email protected],
+            remoteUrl = [email protected],
+        )
     }
 }
 

+ 3 - 27
app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverFetcher.kt

@@ -12,7 +12,6 @@ import coil.request.Options
 import coil.request.Parameters
 import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher.Companion.USE_CUSTOM_COVER
-import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.network.await
 import eu.kanade.tachiyomi.source.online.HttpSource
 import logcat.LogPriority
@@ -26,11 +25,11 @@ import okio.Source
 import okio.buffer
 import okio.sink
 import tachiyomi.core.util.system.logcat
+import tachiyomi.domain.manga.model.Manga
 import tachiyomi.domain.manga.model.MangaCover
 import tachiyomi.domain.source.service.SourceManager
 import uy.kohesive.injekt.injectLazy
 import java.io.File
-import tachiyomi.domain.manga.model.Manga as DomainManga
 
 /**
  * A [Fetcher] that fetches cover image for [Manga] object.
@@ -261,7 +260,7 @@ class MangaCoverFetcher(
         File, URL
     }
 
-    class Factory(
+    class MangaFactory(
         private val callFactoryLazy: Lazy<Call.Factory>,
         private val diskCacheLazy: Lazy<DiskCache>,
     ) : Fetcher.Factory<Manga> {
@@ -270,36 +269,13 @@ class MangaCoverFetcher(
         private val sourceManager: SourceManager by injectLazy()
 
         override fun create(data: Manga, options: Options, imageLoader: ImageLoader): Fetcher {
-            return MangaCoverFetcher(
-                url = data.thumbnail_url,
-                isLibraryManga = data.favorite,
-                options = options,
-                coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnail_url) },
-                customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) },
-                diskCacheKeyLazy = lazy { MangaKeyer().key(data, options) },
-                sourceLazy = lazy { sourceManager.get(data.source) as? HttpSource },
-                callFactoryLazy = callFactoryLazy,
-                diskCacheLazy = diskCacheLazy,
-            )
-        }
-    }
-
-    class DomainMangaFactory(
-        private val callFactoryLazy: Lazy<Call.Factory>,
-        private val diskCacheLazy: Lazy<DiskCache>,
-    ) : Fetcher.Factory<DomainManga> {
-
-        private val coverCache: CoverCache by injectLazy()
-        private val sourceManager: SourceManager by injectLazy()
-
-        override fun create(data: DomainManga, options: Options, imageLoader: ImageLoader): Fetcher {
             return MangaCoverFetcher(
                 url = data.thumbnailUrl,
                 isLibraryManga = data.favorite,
                 options = options,
                 coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnailUrl) },
                 customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) },
-                diskCacheKeyLazy = lazy { DomainMangaKeyer().key(data, options) },
+                diskCacheKeyLazy = lazy { MangaKeyer().key(data, options) },
                 sourceLazy = lazy { sourceManager.get(data.source) as? HttpSource },
                 callFactoryLazy = callFactoryLazy,
                 diskCacheLazy = diskCacheLazy,

+ 5 - 15
app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverKeyer.kt

@@ -4,24 +4,12 @@ import coil.key.Keyer
 import coil.request.Options
 import eu.kanade.domain.manga.model.hasCustomCover
 import eu.kanade.tachiyomi.data.cache.CoverCache
-import eu.kanade.tachiyomi.data.database.models.Manga
-import eu.kanade.tachiyomi.data.database.models.toDomainManga
 import tachiyomi.domain.manga.model.MangaCover
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 import tachiyomi.domain.manga.model.Manga as DomainManga
 
-class MangaKeyer : Keyer<Manga> {
-    override fun key(data: Manga, options: Options): String {
-        return if (data.toDomainManga()!!.hasCustomCover()) {
-            "${data.id};${data.cover_last_modified}"
-        } else {
-            "${data.thumbnail_url};${data.cover_last_modified}"
-        }
-    }
-}
-
-class DomainMangaKeyer : Keyer<DomainManga> {
+class MangaKeyer : Keyer<DomainManga> {
     override fun key(data: DomainManga, options: Options): String {
         return if (data.hasCustomCover()) {
             "${data.id};${data.coverLastModified}"
@@ -31,9 +19,11 @@ class DomainMangaKeyer : Keyer<DomainManga> {
     }
 }
 
-class MangaCoverKeyer : Keyer<MangaCover> {
+class MangaCoverKeyer(
+    private val coverCache: CoverCache = Injekt.get(),
+) : Keyer<MangaCover> {
     override fun key(data: MangaCover, options: Options): String {
-        return if (Injekt.get<CoverCache>().getCustomCoverFile(data.mangaId).exists()) {
+        return if (coverCache.getCustomCoverFile(data.mangaId).exists()) {
             "${data.mangaId};${data.lastModified}"
         } else {
             "${data.url};${data.lastModified}"

+ 0 - 62
app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.kt

@@ -1,62 +0,0 @@
-package eu.kanade.tachiyomi.data.database.models
-
-import eu.kanade.tachiyomi.source.model.SManga
-import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
-import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
-import tachiyomi.domain.manga.model.Manga as DomainManga
-
-interface Manga : SManga {
-
-    var id: Long?
-
-    var source: Long
-
-    var favorite: Boolean
-
-    // last time the chapter list changed in any way
-    var last_update: Long
-
-    var date_added: Long
-
-    var viewer_flags: Int
-
-    var chapter_flags: Int
-
-    var cover_last_modified: Long
-
-    private fun setViewerFlags(flag: Int, mask: Int) {
-        viewer_flags = viewer_flags and mask.inv() or (flag and mask)
-    }
-
-    var readingModeType: Int
-        get() = viewer_flags and ReadingModeType.MASK
-        set(readingMode) = setViewerFlags(readingMode, ReadingModeType.MASK)
-
-    var orientationType: Int
-        get() = viewer_flags and OrientationType.MASK
-        set(rotationType) = setViewerFlags(rotationType, OrientationType.MASK)
-}
-
-fun Manga.toDomainManga(): DomainManga? {
-    val mangaId = id ?: return null
-    return DomainManga(
-        id = mangaId,
-        source = source,
-        favorite = favorite,
-        lastUpdate = last_update,
-        dateAdded = date_added,
-        viewerFlags = viewer_flags.toLong(),
-        chapterFlags = chapter_flags.toLong(),
-        coverLastModified = cover_last_modified,
-        url = url,
-        title = title,
-        artist = artist,
-        author = author,
-        description = description,
-        genre = getGenres(),
-        status = status.toLong(),
-        thumbnailUrl = thumbnail_url,
-        updateStrategy = update_strategy,
-        initialized = initialized,
-    )
-}

+ 0 - 55
app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaImpl.kt

@@ -1,55 +0,0 @@
-package eu.kanade.tachiyomi.data.database.models
-
-import eu.kanade.tachiyomi.source.model.UpdateStrategy
-
-open class MangaImpl : Manga {
-
-    override var id: Long? = null
-
-    override var source: Long = -1
-
-    override lateinit var url: String
-
-    override lateinit var title: String
-
-    override var artist: String? = null
-
-    override var author: String? = null
-
-    override var description: String? = null
-
-    override var genre: String? = null
-
-    override var status: Int = 0
-
-    override var thumbnail_url: String? = null
-
-    override var favorite: Boolean = false
-
-    override var last_update: Long = 0
-
-    override var date_added: Long = 0
-
-    override var update_strategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE
-
-    override var initialized: Boolean = false
-
-    override var viewer_flags: Int = 0
-
-    override var chapter_flags: Int = 0
-
-    override var cover_last_modified: Long = 0
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other == null || javaClass != other.javaClass) return false
-
-        val manga = other as Manga
-        if (url != manga.url) return false
-        return id == manga.id
-    }
-
-    override fun hashCode(): Int {
-        return url.hashCode() + id.hashCode()
-    }
-}

+ 31 - 0
app/src/main/java/eu/kanade/tachiyomi/source/model/SMangaExtensions.kt

@@ -1,6 +1,7 @@
 package eu.kanade.tachiyomi.source.model
 
 import tachiyomi.data.Mangas
+import tachiyomi.domain.manga.model.Manga
 
 fun SManga.copyFrom(other: Mangas) {
     if (other.author != null) {
@@ -29,3 +30,33 @@ fun SManga.copyFrom(other: Mangas) {
         initialized = other.initialized
     }
 }
+
+fun Manga.copyFrom(other: Mangas): Manga {
+    var manga = this
+    if (other.author != null) {
+        manga = manga.copy(author = other.author)
+    }
+
+    if (other.artist != null) {
+        manga = manga.copy(artist = other.artist)
+    }
+
+    if (other.description != null) {
+        manga = manga.copy(description = other.description)
+    }
+
+    if (other.genre != null) {
+        manga = manga.copy(genre = other.genre)
+    }
+
+    if (other.thumbnail_url != null) {
+        manga = manga.copy(thumbnailUrl = other.thumbnail_url)
+    }
+
+    manga = manga.copy(status = other.status)
+
+    if (!initialized) {
+        manga = manga.copy(initialized = other.initialized)
+    }
+    return manga
+}

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

@@ -16,7 +16,6 @@ import eu.kanade.domain.manga.interactor.UpdateManga
 import eu.kanade.domain.manga.model.downloadedFilter
 import eu.kanade.domain.manga.model.isLocal
 import eu.kanade.domain.manga.model.toSManga
-import eu.kanade.domain.track.model.toDbTrack
 import eu.kanade.domain.ui.UiPreferences
 import eu.kanade.presentation.manga.DownloadAction
 import eu.kanade.presentation.manga.components.ChapterDownloadAction
@@ -883,10 +882,9 @@ class MangaInfoScreenModel(
             getTracks.subscribe(manga.id)
                 .catch { logcat(LogPriority.ERROR, it) }
                 .map { tracks ->
-                    val dbTracks = tracks.map { it.toDbTrack() }
                     loggedServices
                         // Map to TrackItem
-                        .map { service -> TrackItem(dbTracks.find { it.sync_id.toLong() == service.id }, service) }
+                        .map { service -> TrackItem(tracks.find { it.syncId == service.id }, service) }
                         // Show only if the service supports this manga's source
                         .filter { (it.service as? EnhancedTrackService)?.accept(source!!) ?: true }
                 }

+ 27 - 28
app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt

@@ -47,7 +47,6 @@ import eu.kanade.presentation.track.TrackServiceSearch
 import eu.kanade.presentation.track.TrackStatusSelector
 import eu.kanade.presentation.util.Screen
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.database.models.Track
 import eu.kanade.tachiyomi.data.track.EnhancedTrackService
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.data.track.TrackService
@@ -71,6 +70,7 @@ import tachiyomi.domain.source.service.SourceManager
 import tachiyomi.domain.track.interactor.DeleteTrack
 import tachiyomi.domain.track.interactor.GetTracks
 import tachiyomi.domain.track.interactor.InsertTrack
+import tachiyomi.domain.track.model.Track
 import tachiyomi.presentation.core.components.material.AlertDialogContent
 import tachiyomi.presentation.core.components.material.padding
 import uy.kohesive.injekt.Injekt
@@ -149,7 +149,7 @@ data class TrackInfoDialogHomeScreen(
                         TrackServiceSearchScreen(
                             mangaId = mangaId,
                             initialQuery = it.track?.title ?: mangaTitle,
-                            currentUrl = it.track?.tracking_url,
+                            currentUrl = it.track?.remoteUrl,
                             serviceId = it.service.id,
                         ),
                     )
@@ -163,7 +163,7 @@ data class TrackInfoDialogHomeScreen(
      * Opens registered tracker url in browser
      */
     private fun openTrackerInBrowser(context: Context, trackItem: TrackItem) {
-        val url = trackItem.track?.tracking_url ?: return
+        val url = trackItem.track?.remoteUrl ?: return
         if (url.isNotBlank()) {
             context.openInBrowser(url)
         }
@@ -218,7 +218,7 @@ data class TrackInfoDialogHomeScreen(
                 for (trackItem in trackItems) {
                     try {
                         val track = trackItem.track ?: continue
-                        val domainTrack = trackItem.service.refresh(track).toDomainTrack() ?: continue
+                        val domainTrack = trackItem.service.refresh(track.toDbTrack()).toDomainTrack() ?: continue
                         insertTrack.await(domainTrack)
 
                         if (trackItem.service is EnhancedTrackService) {
@@ -247,13 +247,12 @@ data class TrackInfoDialogHomeScreen(
             }
         }
 
-        private fun List<tachiyomi.domain.track.model.Track>.mapToTrackItem(): List<TrackItem> {
-            val dbTracks = map { it.toDbTrack() }
+        private fun List<Track>.mapToTrackItem(): List<TrackItem> {
             val loggedServices = Injekt.get<TrackManager>().services.filter { it.isLogged }
             val source = Injekt.get<SourceManager>().getOrStub(sourceId)
             return loggedServices
                 // Map to TrackItem
-                .map { service -> TrackItem(dbTracks.find { it.sync_id.toLong() == service.id }, service) }
+                .map { service -> TrackItem(find { it.syncId == service.id }, service) }
                 // Show only if the service supports this manga's source
                 .filter { (it.service as? EnhancedTrackService)?.accept(source) ?: true }
         }
@@ -291,7 +290,7 @@ private data class TrackStatusSelectorScreen(
     private class Model(
         private val track: Track,
         private val service: TrackService,
-    ) : StateScreenModel<Model.State>(State(track.status)) {
+    ) : StateScreenModel<Model.State>(State(track.status.toInt())) {
 
         fun getSelections(): Map<Int, Int?> {
             return service.getStatusList().associateWith { service.getStatus(it) }
@@ -303,7 +302,7 @@ private data class TrackStatusSelectorScreen(
 
         fun setStatus() {
             coroutineScope.launchNonCancellable {
-                service.setRemoteStatus(track, state.value.selection)
+                service.setRemoteStatus(track.toDbTrack(), state.value.selection)
             }
         }
 
@@ -341,15 +340,15 @@ private data class TrackChapterSelectorScreen(
     private class Model(
         private val track: Track,
         private val service: TrackService,
-    ) : StateScreenModel<Model.State>(State(track.last_chapter_read.toInt())) {
+    ) : StateScreenModel<Model.State>(State(track.lastChapterRead.toInt())) {
 
         fun getRange(): Iterable<Int> {
-            val endRange = if (track.total_chapters > 0) {
-                track.total_chapters
+            val endRange = if (track.totalChapters > 0) {
+                track.totalChapters
             } else {
                 10000
             }
-            return 0..endRange
+            return 0..endRange.toInt()
         }
 
         fun setSelection(selection: Int) {
@@ -358,7 +357,7 @@ private data class TrackChapterSelectorScreen(
 
         fun setChapter() {
             coroutineScope.launchNonCancellable {
-                service.setRemoteLastChapterRead(track, state.value.selection)
+                service.setRemoteLastChapterRead(track.toDbTrack(), state.value.selection)
             }
         }
 
@@ -396,7 +395,7 @@ private data class TrackScoreSelectorScreen(
     private class Model(
         private val track: Track,
         private val service: TrackService,
-    ) : StateScreenModel<Model.State>(State(service.displayScore(track))) {
+    ) : StateScreenModel<Model.State>(State(service.displayScore(track.toDbTrack()))) {
 
         fun getSelections(): List<String> {
             return service.getScoreList()
@@ -408,7 +407,7 @@ private data class TrackScoreSelectorScreen(
 
         fun setScore() {
             coroutineScope.launchNonCancellable {
-                service.setRemoteScore(track, state.value.selection)
+                service.setRemoteScore(track.toDbTrack(), state.value.selection)
             }
         }
 
@@ -436,9 +435,9 @@ private data class TrackDateSelectorScreen(
         }
 
         val canRemove = if (start) {
-            track.started_reading_date > 0
+            track.startDate > 0
         } else {
-            track.finished_reading_date > 0
+            track.finishDate > 0
         }
         TrackDateSelector(
             title = if (start) {
@@ -457,15 +456,15 @@ private data class TrackDateSelectorScreen(
                     return@TrackDateSelector false
                 }
 
-                if (start && track.finished_reading_date > 0) {
+                if (start && track.finishDate > 0) {
                     // Disallow start date to be set later than finish date
-                    val dateFinished = Instant.ofEpochMilli(track.finished_reading_date)
+                    val dateFinished = Instant.ofEpochMilli(track.finishDate)
                         .atZone(ZoneId.systemDefault())
                         .toLocalDate()
                     dateToCheck <= dateFinished
-                } else if (!start && track.started_reading_date > 0) {
+                } else if (!start && track.startDate > 0) {
                     // Disallow end date to be set earlier than start date
-                    val dateStarted = Instant.ofEpochMilli(track.started_reading_date)
+                    val dateStarted = Instant.ofEpochMilli(track.startDate)
                         .atZone(ZoneId.systemDefault())
                         .toLocalDate()
                     dateToCheck >= dateStarted
@@ -489,7 +488,7 @@ private data class TrackDateSelectorScreen(
         // In UTC
         val initialSelection: Long
             get() {
-                val millis = (if (start) track.started_reading_date else track.finished_reading_date)
+                val millis = (if (start) track.startDate else track.finishDate)
                     .takeIf { it != 0L }
                     ?: Instant.now().toEpochMilli()
                 return convertEpochMillisZone(millis, ZoneOffset.systemDefault(), ZoneOffset.UTC)
@@ -501,9 +500,9 @@ private data class TrackDateSelectorScreen(
             val localMillis = convertEpochMillisZone(millis, ZoneOffset.UTC, ZoneOffset.systemDefault())
             coroutineScope.launchNonCancellable {
                 if (start) {
-                    service.setRemoteStartDate(track, localMillis)
+                    service.setRemoteStartDate(track.toDbTrack(), localMillis)
                 } else {
-                    service.setRemoteFinishDate(track, localMillis)
+                    service.setRemoteFinishDate(track.toDbTrack(), localMillis)
                 }
             }
         }
@@ -600,9 +599,9 @@ private data class TrackDateRemoverScreen(
         fun removeDate() {
             coroutineScope.launchNonCancellable {
                 if (start) {
-                    service.setRemoteStartDate(track, 0)
+                    service.setRemoteStartDate(track.toDbTrack(), 0)
                 } else {
-                    service.setRemoteFinishDate(track, 0)
+                    service.setRemoteFinishDate(track.toDbTrack(), 0)
                 }
             }
         }
@@ -679,7 +678,7 @@ data class TrackServiceSearchScreen(
             }
         }
 
-        fun registerTracking(item: Track) {
+        fun registerTracking(item: TrackSearch) {
             coroutineScope.launchNonCancellable { service.registerTracking(item, mangaId) }
         }
 

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

@@ -1,6 +1,6 @@
 package eu.kanade.tachiyomi.ui.manga.track
 
-import eu.kanade.tachiyomi.data.database.models.Track
 import eu.kanade.tachiyomi.data.track.TrackService
+import tachiyomi.domain.track.model.Track
 
 data class TrackItem(val track: Track?, val service: TrackService)