mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 22:37:56 +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:
		| @@ -1,7 +1,10 @@ | ||||
| package eu.kanade.data.manga | ||||
|  | ||||
| import eu.kanade.data.DatabaseHandler | ||||
| import eu.kanade.data.listOfStringsAdapter | ||||
| import eu.kanade.data.toLong | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.domain.manga.model.MangaUpdate | ||||
| import eu.kanade.domain.manga.repository.MangaRepository | ||||
| import eu.kanade.tachiyomi.util.system.logcat | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| @@ -11,6 +14,10 @@ class MangaRepositoryImpl( | ||||
|     private val handler: DatabaseHandler, | ||||
| ) : MangaRepository { | ||||
|  | ||||
|     override suspend fun getMangaById(id: Long): Manga { | ||||
|         return handler.awaitOne { mangasQueries.getMangaById(id, mangaMapper) } | ||||
|     } | ||||
|  | ||||
|     override fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> { | ||||
|         return handler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) } | ||||
|     } | ||||
| @@ -25,11 +32,33 @@ class MangaRepositoryImpl( | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override suspend fun updateLastUpdate(mangaId: Long, lastUpdate: Long) { | ||||
|         try { | ||||
|             handler.await { mangasQueries.updateLastUpdate(lastUpdate, mangaId) } | ||||
|     override suspend fun update(update: MangaUpdate): Boolean { | ||||
|         return try { | ||||
|             handler.await { | ||||
|                 mangasQueries.update( | ||||
|                     source = update.source, | ||||
|                     url = update.url, | ||||
|                     artist = update.artist, | ||||
|                     author = update.author, | ||||
|                     description = update.description, | ||||
|                     genre = update.genre?.let(listOfStringsAdapter::encode), | ||||
|                     title = update.title, | ||||
|                     status = update.status, | ||||
|                     thumbnailUrl = update.thumbnailUrl, | ||||
|                     favorite = update.favorite?.toLong(), | ||||
|                     lastUpdate = update.lastUpdate, | ||||
|                     initialized = update.initialized?.toLong(), | ||||
|                     viewer = update.viewerFlags, | ||||
|                     chapterFlags = update.chapterFlags, | ||||
|                     coverLastModified = update.coverLastModified, | ||||
|                     dateAdded = update.dateAdded, | ||||
|                     mangaId = update.id, | ||||
|                 ) | ||||
|             } | ||||
|             true | ||||
|         } catch (e: Exception) { | ||||
|             logcat(LogPriority.ERROR, e) | ||||
|             false | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -20,8 +20,9 @@ import eu.kanade.domain.history.interactor.RemoveHistoryByMangaId | ||||
| import eu.kanade.domain.history.interactor.UpsertHistory | ||||
| import eu.kanade.domain.history.repository.HistoryRepository | ||||
| import eu.kanade.domain.manga.interactor.GetFavoritesBySourceId | ||||
| import eu.kanade.domain.manga.interactor.GetMangaById | ||||
| import eu.kanade.domain.manga.interactor.ResetViewerFlags | ||||
| import eu.kanade.domain.manga.interactor.UpdateMangaLastUpdate | ||||
| import eu.kanade.domain.manga.interactor.UpdateManga | ||||
| import eu.kanade.domain.manga.repository.MangaRepository | ||||
| import eu.kanade.domain.source.interactor.GetEnabledSources | ||||
| import eu.kanade.domain.source.interactor.GetLanguagesWithSources | ||||
| @@ -43,9 +44,10 @@ class DomainModule : InjektModule { | ||||
|     override fun InjektRegistrar.registerInjectables() { | ||||
|         addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) } | ||||
|         addFactory { GetFavoritesBySourceId(get()) } | ||||
|         addFactory { GetMangaById(get()) } | ||||
|         addFactory { GetNextChapter(get()) } | ||||
|         addFactory { ResetViewerFlags(get()) } | ||||
|         addFactory { UpdateMangaLastUpdate(get()) } | ||||
|         addFactory { UpdateManga(get()) } | ||||
|  | ||||
|         addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) } | ||||
|         addFactory { UpdateChapter(get()) } | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import eu.kanade.domain.chapter.model.Chapter | ||||
| import eu.kanade.domain.chapter.model.toChapterUpdate | ||||
| import eu.kanade.domain.chapter.model.toDbChapter | ||||
| import eu.kanade.domain.chapter.repository.ChapterRepository | ||||
| import eu.kanade.domain.manga.interactor.UpdateMangaLastUpdate | ||||
| import eu.kanade.domain.manga.interactor.UpdateManga | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.domain.manga.model.toDbManga | ||||
| import eu.kanade.tachiyomi.data.download.DownloadManager | ||||
| @@ -24,7 +24,7 @@ class SyncChaptersWithSource( | ||||
|     private val downloadManager: DownloadManager = Injekt.get(), | ||||
|     private val chapterRepository: ChapterRepository = Injekt.get(), | ||||
|     private val shouldUpdateDbChapter: ShouldUpdateDbChapter = Injekt.get(), | ||||
|     private val updateMangaLastUpdate: UpdateMangaLastUpdate = Injekt.get(), | ||||
|     private val updateManga: UpdateManga = Injekt.get(), | ||||
| ) { | ||||
|  | ||||
|     suspend fun await( | ||||
| @@ -171,7 +171,7 @@ class SyncChaptersWithSource( | ||||
|  | ||||
|         // Set this manga as updated since chapters were changed | ||||
|         // Note that last_update actually represents last time the chapter list changed at all | ||||
|         updateMangaLastUpdate.await(manga.id, Date().time) | ||||
|         updateManga.awaitUpdateLastUpdate(manga.id) | ||||
|  | ||||
|         @Suppress("ConvertArgumentToSet") // See tachiyomiorg/tachiyomi#6372. | ||||
|         return Pair(updatedToAdd.subtract(reAdded).toList(), toDelete.subtract(reAdded).toList()) | ||||
|   | ||||
| @@ -0,0 +1,20 @@ | ||||
| package eu.kanade.domain.manga.interactor | ||||
|  | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.domain.manga.repository.MangaRepository | ||||
| import eu.kanade.tachiyomi.util.system.logcat | ||||
| import logcat.LogPriority | ||||
|  | ||||
| class GetMangaById( | ||||
|     private val mangaRepository: MangaRepository, | ||||
| ) { | ||||
|  | ||||
|     suspend fun await(id: Long): Manga? { | ||||
|         return try { | ||||
|             mangaRepository.getMangaById(id) | ||||
|         } catch (e: Exception) { | ||||
|             logcat(LogPriority.ERROR, e) | ||||
|             null | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,61 @@ | ||||
| package eu.kanade.domain.manga.interactor | ||||
|  | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.domain.manga.model.MangaUpdate | ||||
| import eu.kanade.domain.manga.model.hasCustomCover | ||||
| import eu.kanade.domain.manga.model.isLocal | ||||
| import eu.kanade.domain.manga.model.toDbManga | ||||
| import eu.kanade.domain.manga.repository.MangaRepository | ||||
| import eu.kanade.tachiyomi.data.cache.CoverCache | ||||
| import tachiyomi.source.model.MangaInfo | ||||
| import java.util.Date | ||||
|  | ||||
| class UpdateManga( | ||||
|     private val mangaRepository: MangaRepository, | ||||
| ) { | ||||
|  | ||||
|     suspend fun awaitUpdateFromSource( | ||||
|         localManga: Manga, | ||||
|         remoteManga: MangaInfo, | ||||
|         manualFetch: Boolean, | ||||
|         coverCache: CoverCache, | ||||
|     ): Boolean { | ||||
|         // if the manga isn't a favorite, set its title from source and update in db | ||||
|         val title = if (!localManga.favorite) remoteManga.title else null | ||||
|  | ||||
|         // Never refresh covers if the url is empty to avoid "losing" existing covers | ||||
|         val updateCover = remoteManga.cover.isNotEmpty() && (manualFetch || localManga.thumbnailUrl != remoteManga.cover) | ||||
|         val coverLastModified = if (updateCover) { | ||||
|             when { | ||||
|                 localManga.isLocal() -> Date().time | ||||
|                 localManga.hasCustomCover(coverCache) -> { | ||||
|                     coverCache.deleteFromCache(localManga.toDbManga(), false) | ||||
|                     null | ||||
|                 } | ||||
|                 else -> { | ||||
|                     coverCache.deleteFromCache(localManga.toDbManga(), false) | ||||
|                     Date().time | ||||
|                 } | ||||
|             } | ||||
|         } else null | ||||
|  | ||||
|         return mangaRepository.update( | ||||
|             MangaUpdate( | ||||
|                 id = localManga.id, | ||||
|                 title = title?.takeIf { it.isNotEmpty() }, | ||||
|                 coverLastModified = coverLastModified, | ||||
|                 author = remoteManga.author, | ||||
|                 artist = remoteManga.artist, | ||||
|                 description = remoteManga.description, | ||||
|                 genre = remoteManga.genres, | ||||
|                 thumbnailUrl = remoteManga.cover.takeIf { it.isNotEmpty() }, | ||||
|                 status = remoteManga.status.toLong(), | ||||
|                 initialized = true, | ||||
|             ), | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     suspend fun awaitUpdateLastUpdate(mangaId: Long): Boolean { | ||||
|         return mangaRepository.update(MangaUpdate(id = mangaId, lastUpdate = Date().time)) | ||||
|     } | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| package eu.kanade.domain.manga.interactor | ||||
|  | ||||
| import eu.kanade.domain.manga.repository.MangaRepository | ||||
|  | ||||
| class UpdateMangaLastUpdate( | ||||
|     private val mangaRepository: MangaRepository, | ||||
| ) { | ||||
|  | ||||
|     suspend fun await(mangaId: Long, lastUpdate: Long) { | ||||
|         mangaRepository.updateLastUpdate(mangaId, lastUpdate) | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,11 @@ | ||||
| package eu.kanade.domain.manga.model | ||||
|  | ||||
| import eu.kanade.tachiyomi.data.cache.CoverCache | ||||
| import eu.kanade.tachiyomi.source.LocalSource | ||||
| import eu.kanade.tachiyomi.source.model.SManga | ||||
| import tachiyomi.source.model.MangaInfo | ||||
| import uy.kohesive.injekt.Injekt | ||||
| import uy.kohesive.injekt.api.get | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga as DbManga | ||||
|  | ||||
| data class Manga( | ||||
| @@ -62,3 +67,20 @@ fun Manga.toDbManga(): DbManga = DbManga.create(url, title, source).also { | ||||
|     it.chapter_flags = chapterFlags.toInt() | ||||
|     it.cover_last_modified = coverLastModified | ||||
| } | ||||
|  | ||||
| fun Manga.toMangaInfo(): MangaInfo = MangaInfo( | ||||
|     artist = artist ?: "", | ||||
|     author = author ?: "", | ||||
|     cover = thumbnailUrl ?: "", | ||||
|     description = description ?: "", | ||||
|     genres = genre ?: emptyList(), | ||||
|     key = url, | ||||
|     status = status.toInt(), | ||||
|     title = title, | ||||
| ) | ||||
|  | ||||
| fun Manga.isLocal(): Boolean = source == LocalSource.ID | ||||
|  | ||||
| fun Manga.hasCustomCover(coverCache: CoverCache = Injekt.get()): Boolean { | ||||
|     return coverCache.getCustomCoverFile(id).exists() | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,21 @@ | ||||
| package eu.kanade.domain.manga.model | ||||
|  | ||||
| data class MangaUpdate( | ||||
|     val id: Long, | ||||
|     val source: Long? = null, | ||||
|     val favorite: Boolean? = null, | ||||
|     val lastUpdate: Long? = null, | ||||
|     val dateAdded: Long? = null, | ||||
|     val viewerFlags: Long? = null, | ||||
|     val chapterFlags: Long? = null, | ||||
|     val coverLastModified: Long? = null, | ||||
|     val url: String? = null, | ||||
|     val title: String? = null, | ||||
|     val artist: String? = null, | ||||
|     val author: String? = null, | ||||
|     val description: String? = null, | ||||
|     val genre: List<String>? = null, | ||||
|     val status: Long? = null, | ||||
|     val thumbnailUrl: String? = null, | ||||
|     val initialized: Boolean? = null, | ||||
| ) | ||||
| @@ -1,13 +1,16 @@ | ||||
| package eu.kanade.domain.manga.repository | ||||
|  | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.domain.manga.model.MangaUpdate | ||||
| import kotlinx.coroutines.flow.Flow | ||||
|  | ||||
| interface MangaRepository { | ||||
|  | ||||
|     suspend fun getMangaById(id: Long): Manga | ||||
|  | ||||
|     fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> | ||||
|  | ||||
|     suspend fun resetViewerFlags(): Boolean | ||||
|  | ||||
|     suspend fun updateLastUpdate(mangaId: Long, lastUpdate: Long) | ||||
|     suspend fun update(update: MangaUpdate): Boolean | ||||
| } | ||||
|   | ||||
| @@ -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() { | ||||
|   | ||||
| @@ -58,7 +58,22 @@ deleteMangasNotInLibraryBySourceIds: | ||||
| DELETE FROM mangas | ||||
| WHERE favorite = 0 AND source IN :sourceIds; | ||||
|  | ||||
| updateLastUpdate: | ||||
| UPDATE mangas | ||||
| SET last_update = :lastUpdate | ||||
| update: | ||||
| UPDATE mangas SET | ||||
|     source = coalesce(:source, source), | ||||
|     url = coalesce(:url, url), | ||||
|     artist = coalesce(:artist, artist), | ||||
|     author = coalesce(:author, author), | ||||
|     description = coalesce(:description, description), | ||||
|     genre = coalesce(:genre, genre), | ||||
|     title = coalesce(:title, title), | ||||
|     status = coalesce(:status, status), | ||||
|     thumbnail_url = coalesce(:thumbnailUrl, thumbnail_url), | ||||
|     favorite = coalesce(:favorite, favorite), | ||||
|     last_update = coalesce(:lastUpdate, last_update), | ||||
|     initialized = coalesce(:initialized, initialized), | ||||
|     viewer = coalesce(:viewer, viewer), | ||||
|     chapter_flags = coalesce(:chapterFlags, chapter_flags), | ||||
|     cover_last_modified = coalesce(:coverLastModified, cover_last_modified), | ||||
|     date_added = coalesce(:dateAdded, date_added) | ||||
| WHERE _id = :mangaId; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user