diff --git a/app/build.gradle b/app/build.gradle index 5ce95c226..8470855f2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -81,7 +81,7 @@ afterEvaluate { } dependencies { //noinspection GradleDependency - implementation('com.github.KotatsuApp:kotatsu-parsers:74ffe9418b') { + implementation('com.github.KotatsuApp:kotatsu-parsers:03b4fc9f00') { exclude group: 'org.json', module: 'json' } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/MangaDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/MangaDao.kt index efca0e36b..7f078bb7f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/MangaDao.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/MangaDao.kt @@ -1,6 +1,12 @@ package org.koitharu.kotatsu.core.db.dao -import androidx.room.* +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.Transaction +import androidx.room.Update +import androidx.room.Upsert import org.koitharu.kotatsu.core.db.entity.MangaEntity import org.koitharu.kotatsu.core.db.entity.MangaTagsEntity import org.koitharu.kotatsu.core.db.entity.MangaWithTags @@ -21,8 +27,8 @@ abstract class MangaDao { @Query("SELECT * FROM manga WHERE (title LIKE :query OR alt_title LIKE :query) AND source = :source AND manga_id IN (SELECT manga_id FROM favourites UNION SELECT manga_id FROM history) LIMIT :limit") abstract suspend fun searchByTitle(query: String, source: String, limit: Int): List - @Insert(onConflict = OnConflictStrategy.IGNORE) - abstract suspend fun insert(manga: MangaEntity): Long + @Upsert + abstract suspend fun upsert(manga: MangaEntity) @Update(onConflict = OnConflictStrategy.IGNORE) abstract suspend fun update(manga: MangaEntity): Int @@ -35,15 +41,13 @@ abstract class MangaDao { @Transaction open suspend fun upsert(manga: MangaEntity, tags: Iterable? = null) { - if (update(manga) <= 0) { - insert(manga) - if (tags != null) { - clearTagRelation(manga.id) - tags.map { - MangaTagsEntity(manga.id, it.id) - }.forEach { - insertTagRelation(it) - } + upsert(manga) + if (tags != null) { + clearTagRelation(manga.id) + tags.map { + MangaTagsEntity(manga.id, it.id) + }.forEach { + insertTagRelation(it) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DoubleMangaLoadUseCase.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DoubleMangaLoadUseCase.kt index 143d1ae24..e228acb57 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DoubleMangaLoadUseCase.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DoubleMangaLoadUseCase.kt @@ -8,9 +8,11 @@ import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.details.domain.model.DoubleManga +import org.koitharu.kotatsu.explore.domain.RecoverMangaUseCase import org.koitharu.kotatsu.local.data.LocalMangaRepository import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.util.recoverNotNull import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import javax.inject.Inject @@ -18,6 +20,7 @@ class DoubleMangaLoadUseCase @Inject constructor( private val mangaDataRepository: MangaDataRepository, private val localMangaRepository: LocalMangaRepository, private val mangaRepositoryFactory: MangaRepository.Factory, + private val recoverUseCase: RecoverMangaUseCase, ) { suspend operator fun invoke(manga: Manga): DoubleManga = coroutineScope { @@ -58,6 +61,12 @@ class DoubleMangaLoadUseCase @Inject constructor( } ?: return null val repository = mangaRepositoryFactory.create(seed.source) repository.getDetails(seed) + }.recoverNotNull { e -> + if (e is NotFoundException) { + recoverUseCase(manga) + } else { + null + } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/explore/domain/RecoverMangaUseCase.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/domain/RecoverMangaUseCase.kt new file mode 100644 index 000000000..50aecfc4e --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/explore/domain/RecoverMangaUseCase.kt @@ -0,0 +1,52 @@ +package org.koitharu.kotatsu.explore.domain + +import org.koitharu.kotatsu.core.model.isLocal +import org.koitharu.kotatsu.core.parser.MangaDataRepository +import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import javax.inject.Inject + +class RecoverMangaUseCase @Inject constructor( + private val mangaDataRepository: MangaDataRepository, + private val repositoryFactory: MangaRepository.Factory, +) { + + suspend operator fun invoke(manga: Manga): Manga? = runCatchingCancellable { + if (manga.isLocal) { + return@runCatchingCancellable null + } + val repository = repositoryFactory.create(manga.source) + val list = repository.getList(offset = 0, query = manga.title) + val newManga = list.find { x -> x.title == manga.title }?.let { + repository.getDetails(it) + } ?: return@runCatchingCancellable null + val merged = merge(manga, newManga) + mangaDataRepository.storeManga(merged) + merged + }.onFailure { + it.printStackTraceDebug() + }.getOrNull() + + private fun merge( + broken: Manga, + current: Manga, + ) = Manga( + id = broken.id, + title = current.title, + altTitle = current.altTitle, + url = current.url, + publicUrl = current.publicUrl, + rating = current.rating, + isNsfw = current.isNsfw, + coverUrl = current.coverUrl, + tags = current.tags, + state = current.state, + author = current.author, + largeCoverUrl = current.largeCoverUrl, + description = current.description, + chapters = current.chapters, + source = current.source, + ) +}