Update manga metadata on library update with sqldelight (#7293)

Co-Authored-By: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>

Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
This commit is contained in:
AntsyLich
2022-06-12 20:21:45 +06:00
committed by GitHub
parent 5fbf454652
commit 5bb78eb77f
13 changed files with 220 additions and 96 deletions

View File

@@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.data.database.resolvers.LibraryMangaGetResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaCoverLastModifiedPutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaFavoritePutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaFlagsPutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaLastUpdatedPutResolver
import eu.kanade.tachiyomi.data.database.tables.CategoryTable
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
@@ -101,11 +100,6 @@ interface MangaQueries : DbProvider {
.withPutResolver(MangaFlagsPutResolver(MangaTable.COL_VIEWER, Manga::viewer_flags))
.prepare()
fun updateLastUpdated(manga: Manga) = db.put()
.`object`(manga)
.withPutResolver(MangaLastUpdatedPutResolver())
.prepare()
fun updateMangaFavorite(manga: Manga) = db.put()
.`object`(manga)
.withPutResolver(MangaFavoritePutResolver())

View File

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

View File

@@ -7,6 +7,11 @@ import android.os.IBinder
import android.os.PowerManager
import androidx.core.content.ContextCompat
import eu.kanade.data.chapter.NoChaptersException
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.domain.manga.interactor.GetMangaById
import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.toMangaInfo
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
@@ -14,6 +19,7 @@ import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toDomainManga
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.DownloadService
@@ -29,10 +35,8 @@ import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.UnmeteredSource
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toMangaInfo
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithTrackServiceTwoWay
import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.prepUpdateCover
@@ -55,12 +59,15 @@ import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import logcat.LogPriority
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.File
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
import eu.kanade.domain.chapter.model.Chapter as DomainChapter
import eu.kanade.domain.manga.model.Manga as DomainManga
/**
* This class will take care of updating the chapters of the manga from the library. It can be
@@ -77,6 +84,9 @@ class LibraryUpdateService(
val downloadManager: DownloadManager = Injekt.get(),
val trackManager: TrackManager = Injekt.get(),
val coverCache: CoverCache = Injekt.get(),
private val getMangaById: GetMangaById = Injekt.get(),
private val updateManga: UpdateManga = Injekt.get(),
private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get(),
) : Service() {
private lateinit var wakeLock: PowerManager.WakeLock
@@ -302,7 +312,7 @@ class LibraryUpdateService(
}
// Don't continue to update if manga not in library
db.getManga(manga.id!!).executeAsBlocking() ?: return@forEach
manga.id?.let { getMangaById.await(it) } ?: return@forEach
withUpdateNotification(
currentlyUpdatingManga,
@@ -322,19 +332,22 @@ class LibraryUpdateService(
else -> {
// Convert to the manga that contains new chapters
val (newChapters, _) = updateManga(mangaWithNotif)
mangaWithNotif.toDomainManga()?.let { domainManga ->
val (newChapters, _) = updateManga(domainManga)
val newDbChapters = newChapters.map { it.toDbChapter() }
if (newChapters.isNotEmpty()) {
if (mangaWithNotif.shouldDownloadNewChapters(db, preferences)) {
downloadChapters(mangaWithNotif, newChapters)
hasDownloads.set(true)
if (newChapters.isNotEmpty()) {
if (mangaWithNotif.shouldDownloadNewChapters(db, preferences)) {
downloadChapters(mangaWithNotif, newDbChapters)
hasDownloads.set(true)
}
// Convert to the manga that contains new chapters
newUpdates.add(
mangaWithNotif to newDbChapters.sortedByDescending { ch -> ch.source_order }
.toTypedArray(),
)
}
// Convert to the manga that contains new chapters
newUpdates.add(
mangaWithNotif to newChapters.sortedByDescending { ch -> ch.source_order }
.toTypedArray(),
)
}
}
}
@@ -394,39 +407,27 @@ class LibraryUpdateService(
* @param manga the manga to update.
* @return a pair of the inserted and removed chapters.
*/
private suspend fun updateManga(manga: Manga): Pair<List<Chapter>, List<Chapter>> {
private suspend fun updateManga(manga: DomainManga): Pair<List<DomainChapter>, List<DomainChapter>> {
val source = sourceManager.getOrStub(manga.source)
var updatedManga: SManga = manga
val mangaInfo: MangaInfo = manga.toMangaInfo()
// Update manga details metadata
// Update manga metadata if needed
if (preferences.autoUpdateMetadata()) {
val updatedMangaDetails = source.getMangaDetails(manga.toMangaInfo())
val sManga = updatedMangaDetails.toSManga()
// Avoid "losing" existing cover
if (!sManga.thumbnail_url.isNullOrEmpty()) {
manga.prepUpdateCover(coverCache, sManga, false)
} else {
sManga.thumbnail_url = manga.thumbnail_url
}
updatedManga = sManga
val updatedMangaInfo = source.getMangaDetails(manga.toMangaInfo())
updateManga.awaitUpdateFromSource(manga, updatedMangaInfo, manualFetch = false, coverCache)
}
val chapters = source.getChapterList(updatedManga.toMangaInfo())
val chapters = source.getChapterList(mangaInfo)
.map { it.toSChapter() }
// Get manga from database to account for if it was removed during the update
val dbManga = db.getManga(manga.id!!).executeAsBlocking()
val dbManga = getMangaById.await(manga.id)
?: return Pair(emptyList(), emptyList())
// Copy into [dbManga] to retain favourite value
dbManga.copyFrom(updatedManga)
db.insertManga(dbManga).executeAsBlocking()
// [dbmanga] was used so that manga data doesn't get overwritten
// in case manga gets new chapter
return syncChaptersWithSource(chapters, dbManga, source)
return syncChaptersWithSource.await(chapters, dbManga, source)
}
private suspend fun updateCovers() {