mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-13 12:38:58 +01:00
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:
@@ -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())
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user