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
This commit is contained in:
Andreas 2023-03-19 18:11:58 +01:00 committed by GitHub
parent c955ac6a66
commit dfdb688b43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 231 additions and 348 deletions

View file

@ -2,6 +2,7 @@ package eu.kanade.domain.chapter.model
import eu.kanade.tachiyomi.data.database.models.ChapterImpl import eu.kanade.tachiyomi.data.database.models.ChapterImpl
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import tachiyomi.data.Chapters
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import eu.kanade.tachiyomi.data.database.models.Chapter as DbChapter 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 { fun Chapter.toDbChapter(): DbChapter = ChapterImpl().also {
it.id = id it.id = id
it.manga_id = mangaId it.manga_id = mangaId

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,24 +4,12 @@ import coil.key.Keyer
import coil.request.Options import coil.request.Options
import eu.kanade.domain.manga.model.hasCustomCover import eu.kanade.domain.manga.model.hasCustomCover
import eu.kanade.tachiyomi.data.cache.CoverCache 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 tachiyomi.domain.manga.model.MangaCover
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import tachiyomi.domain.manga.model.Manga as DomainManga import tachiyomi.domain.manga.model.Manga as DomainManga
class MangaKeyer : Keyer<Manga> { class MangaKeyer : Keyer<DomainManga> {
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> {
override fun key(data: DomainManga, options: Options): String { override fun key(data: DomainManga, options: Options): String {
return if (data.hasCustomCover()) { return if (data.hasCustomCover()) {
"${data.id};${data.coverLastModified}" "${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 { 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}" "${data.mangaId};${data.lastModified}"
} else { } else {
"${data.url};${data.lastModified}" "${data.url};${data.lastModified}"

View file

@ -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,
)
}

View file

@ -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()
}
}

View file

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.source.model package eu.kanade.tachiyomi.source.model
import tachiyomi.data.Mangas import tachiyomi.data.Mangas
import tachiyomi.domain.manga.model.Manga
fun SManga.copyFrom(other: Mangas) { fun SManga.copyFrom(other: Mangas) {
if (other.author != null) { if (other.author != null) {
@ -29,3 +30,33 @@ fun SManga.copyFrom(other: Mangas) {
initialized = other.initialized 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
}

View file

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

View file

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

View file

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