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
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 220 additions and 96 deletions

View file

@ -1,7 +1,10 @@
package eu.kanade.data.manga package eu.kanade.data.manga
import eu.kanade.data.DatabaseHandler 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.Manga
import eu.kanade.domain.manga.model.MangaUpdate
import eu.kanade.domain.manga.repository.MangaRepository import eu.kanade.domain.manga.repository.MangaRepository
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -11,6 +14,10 @@ class MangaRepositoryImpl(
private val handler: DatabaseHandler, private val handler: DatabaseHandler,
) : MangaRepository { ) : MangaRepository {
override suspend fun getMangaById(id: Long): Manga {
return handler.awaitOne { mangasQueries.getMangaById(id, mangaMapper) }
}
override fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> { override fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> {
return handler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) } return handler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) }
} }
@ -25,11 +32,33 @@ class MangaRepositoryImpl(
} }
} }
override suspend fun updateLastUpdate(mangaId: Long, lastUpdate: Long) { override suspend fun update(update: MangaUpdate): Boolean {
try { return try {
handler.await { mangasQueries.updateLastUpdate(lastUpdate, mangaId) } 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) { } catch (e: Exception) {
logcat(LogPriority.ERROR, e) logcat(LogPriority.ERROR, e)
false
} }
} }
} }

View file

@ -20,8 +20,9 @@ import eu.kanade.domain.history.interactor.RemoveHistoryByMangaId
import eu.kanade.domain.history.interactor.UpsertHistory import eu.kanade.domain.history.interactor.UpsertHistory
import eu.kanade.domain.history.repository.HistoryRepository import eu.kanade.domain.history.repository.HistoryRepository
import eu.kanade.domain.manga.interactor.GetFavoritesBySourceId 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.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.manga.repository.MangaRepository
import eu.kanade.domain.source.interactor.GetEnabledSources import eu.kanade.domain.source.interactor.GetEnabledSources
import eu.kanade.domain.source.interactor.GetLanguagesWithSources import eu.kanade.domain.source.interactor.GetLanguagesWithSources
@ -43,9 +44,10 @@ class DomainModule : InjektModule {
override fun InjektRegistrar.registerInjectables() { override fun InjektRegistrar.registerInjectables() {
addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) } addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) }
addFactory { GetFavoritesBySourceId(get()) } addFactory { GetFavoritesBySourceId(get()) }
addFactory { GetMangaById(get()) }
addFactory { GetNextChapter(get()) } addFactory { GetNextChapter(get()) }
addFactory { ResetViewerFlags(get()) } addFactory { ResetViewerFlags(get()) }
addFactory { UpdateMangaLastUpdate(get()) } addFactory { UpdateManga(get()) }
addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) } addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
addFactory { UpdateChapter(get()) } addFactory { UpdateChapter(get()) }

View file

@ -5,7 +5,7 @@ import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.model.toChapterUpdate import eu.kanade.domain.chapter.model.toChapterUpdate
import eu.kanade.domain.chapter.model.toDbChapter import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.domain.chapter.repository.ChapterRepository 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.Manga
import eu.kanade.domain.manga.model.toDbManga import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
@ -24,7 +24,7 @@ class SyncChaptersWithSource(
private val downloadManager: DownloadManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(),
private val chapterRepository: ChapterRepository = Injekt.get(), private val chapterRepository: ChapterRepository = Injekt.get(),
private val shouldUpdateDbChapter: ShouldUpdateDbChapter = Injekt.get(), private val shouldUpdateDbChapter: ShouldUpdateDbChapter = Injekt.get(),
private val updateMangaLastUpdate: UpdateMangaLastUpdate = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(),
) { ) {
suspend fun await( suspend fun await(
@ -171,7 +171,7 @@ class SyncChaptersWithSource(
// Set this manga as updated since chapters were changed // Set this manga as updated since chapters were changed
// Note that last_update actually represents last time the chapter list changed at all // 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. @Suppress("ConvertArgumentToSet") // See tachiyomiorg/tachiyomi#6372.
return Pair(updatedToAdd.subtract(reAdded).toList(), toDelete.subtract(reAdded).toList()) return Pair(updatedToAdd.subtract(reAdded).toList(), toDelete.subtract(reAdded).toList())

View file

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

View file

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

View file

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

View file

@ -1,6 +1,11 @@
package eu.kanade.domain.manga.model 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 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 import eu.kanade.tachiyomi.data.database.models.Manga as DbManga
data class Manga( data class Manga(
@ -62,3 +67,20 @@ fun Manga.toDbManga(): DbManga = DbManga.create(url, title, source).also {
it.chapter_flags = chapterFlags.toInt() it.chapter_flags = chapterFlags.toInt()
it.cover_last_modified = coverLastModified 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()
}

View file

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

View file

@ -1,13 +1,16 @@
package eu.kanade.domain.manga.repository package eu.kanade.domain.manga.repository
import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.MangaUpdate
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
interface MangaRepository { interface MangaRepository {
suspend fun getMangaById(id: Long): Manga
fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>>
suspend fun resetViewerFlags(): Boolean suspend fun resetViewerFlags(): Boolean
suspend fun updateLastUpdate(mangaId: Long, lastUpdate: Long) suspend fun update(update: MangaUpdate): Boolean
} }

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.MangaCoverLastModifiedPutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaFavoritePutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaFavoritePutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaFlagsPutResolver 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.CategoryTable
import eu.kanade.tachiyomi.data.database.tables.ChapterTable import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
@ -101,11 +100,6 @@ interface MangaQueries : DbProvider {
.withPutResolver(MangaFlagsPutResolver(MangaTable.COL_VIEWER, Manga::viewer_flags)) .withPutResolver(MangaFlagsPutResolver(MangaTable.COL_VIEWER, Manga::viewer_flags))
.prepare() .prepare()
fun updateLastUpdated(manga: Manga) = db.put()
.`object`(manga)
.withPutResolver(MangaLastUpdatedPutResolver())
.prepare()
fun updateMangaFavorite(manga: Manga) = db.put() fun updateMangaFavorite(manga: Manga) = db.put()
.`object`(manga) .`object`(manga)
.withPutResolver(MangaFavoritePutResolver()) .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 android.os.PowerManager
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import eu.kanade.data.chapter.NoChaptersException 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.R
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper 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.Chapter
import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.database.models.Manga 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.database.models.toMangaInfo
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.DownloadService 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.SourceManager
import eu.kanade.tachiyomi.source.UnmeteredSource import eu.kanade.tachiyomi.source.UnmeteredSource
import eu.kanade.tachiyomi.source.model.SManga 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.toSChapter
import eu.kanade.tachiyomi.source.model.toSManga 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.chapter.syncChaptersWithTrackServiceTwoWay
import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.prepUpdateCover import eu.kanade.tachiyomi.util.prepUpdateCover
@ -55,12 +59,15 @@ import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.sync.withPermit
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.source.model.MangaInfo
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.File import java.io.File
import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger 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 * 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 downloadManager: DownloadManager = Injekt.get(),
val trackManager: TrackManager = Injekt.get(), val trackManager: TrackManager = Injekt.get(),
val coverCache: CoverCache = 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() { ) : Service() {
private lateinit var wakeLock: PowerManager.WakeLock private lateinit var wakeLock: PowerManager.WakeLock
@ -302,7 +312,7 @@ class LibraryUpdateService(
} }
// Don't continue to update if manga not in library // 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( withUpdateNotification(
currentlyUpdatingManga, currentlyUpdatingManga,
@ -322,19 +332,22 @@ class LibraryUpdateService(
else -> { else -> {
// Convert to the manga that contains new chapters // 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 (newChapters.isNotEmpty()) {
if (mangaWithNotif.shouldDownloadNewChapters(db, preferences)) { if (mangaWithNotif.shouldDownloadNewChapters(db, preferences)) {
downloadChapters(mangaWithNotif, newChapters) downloadChapters(mangaWithNotif, newDbChapters)
hasDownloads.set(true) 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. * @param manga the manga to update.
* @return a pair of the inserted and removed chapters. * @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) 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()) { if (preferences.autoUpdateMetadata()) {
val updatedMangaDetails = source.getMangaDetails(manga.toMangaInfo()) val updatedMangaInfo = source.getMangaDetails(manga.toMangaInfo())
val sManga = updatedMangaDetails.toSManga() updateManga.awaitUpdateFromSource(manga, updatedMangaInfo, manualFetch = false, coverCache)
// Avoid "losing" existing cover
if (!sManga.thumbnail_url.isNullOrEmpty()) {
manga.prepUpdateCover(coverCache, sManga, false)
} else {
sManga.thumbnail_url = manga.thumbnail_url
}
updatedManga = sManga
} }
val chapters = source.getChapterList(updatedManga.toMangaInfo()) val chapters = source.getChapterList(mangaInfo)
.map { it.toSChapter() } .map { it.toSChapter() }
// Get manga from database to account for if it was removed during the update // 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()) ?: 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 // [dbmanga] was used so that manga data doesn't get overwritten
// in case manga gets new chapter // in case manga gets new chapter
return syncChaptersWithSource(chapters, dbManga, source) return syncChaptersWithSource.await(chapters, dbManga, source)
} }
private suspend fun updateCovers() { private suspend fun updateCovers() {

View file

@ -58,7 +58,22 @@ deleteMangasNotInLibraryBySourceIds:
DELETE FROM mangas DELETE FROM mangas
WHERE favorite = 0 AND source IN :sourceIds; WHERE favorite = 0 AND source IN :sourceIds;
updateLastUpdate: update:
UPDATE mangas UPDATE mangas SET
SET last_update = :lastUpdate 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; WHERE _id = :mangaId;