Remove 1.x source models (#7781)

(cherry picked from commit e36e9d9d5c)

# Conflicts:
#	app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt
#	app/src/main/java/eu/kanade/domain/manga/model/Manga.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt
#	app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt
#	app/src/main/java/eu/kanade/tachiyomi/source/Source.kt
#	app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt
#	app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchPresenter.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
This commit is contained in:
stevenyomi
2022-08-19 02:07:13 +08:00
committed by Jobobby04
parent fff031cf1c
commit 39e0d7f4e8
58 changed files with 414 additions and 509 deletions
@@ -2,7 +2,6 @@ package eu.kanade.domain.manga.interactor
import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.PagePreview
import eu.kanade.domain.manga.model.toMangaInfo
import eu.kanade.tachiyomi.data.cache.PagePreviewCache
import eu.kanade.tachiyomi.source.PagePreviewSource
import eu.kanade.tachiyomi.source.Source
@@ -19,7 +18,7 @@ class GetPagePreviews(
val pagePreviews = try {
pagePreviewCache.getPageListFromCache(manga, page)
} catch (e: Exception) {
source.getPagePreviewList(manga.toMangaInfo(), page).also {
source.getPagePreviewList(manga.toSManga(), page).also {
pagePreviewCache.putPageListToCache(manga, it)
}
}
@@ -8,7 +8,7 @@ import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.domain.manga.repository.MangaRepository
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.download.DownloadManager
import tachiyomi.source.model.MangaInfo
import eu.kanade.tachiyomi.source.model.SManga
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Date
@@ -27,7 +27,7 @@ class UpdateManga(
suspend fun awaitUpdateFromSource(
localManga: Manga,
remoteManga: MangaInfo,
remoteManga: SManga,
manualFetch: Boolean,
coverCache: CoverCache = Injekt.get(),
// SY -->
@@ -41,10 +41,11 @@ class UpdateManga(
} else null
// SY <--
// 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) {
val coverLastModified =
when {
// Never refresh covers if the url is empty to avoid "losing" existing covers
remoteManga.thumbnail_url.isNullOrEmpty() -> null
!manualFetch && localManga.thumbnailUrl == remoteManga.thumbnail_url -> null
localManga.isLocal() -> Date().time
localManga.hasCustomCover(coverCache) -> {
coverCache.deleteFromCache(localManga.toDbManga(), false)
@@ -55,7 +56,6 @@ class UpdateManga(
Date().time
}
}
} else null
return mangaRepository.update(
MangaUpdate(
@@ -65,8 +65,8 @@ class UpdateManga(
author = remoteManga.author,
artist = remoteManga.artist,
description = remoteManga.description,
genre = remoteManga.genres,
thumbnailUrl = remoteManga.cover.takeIf { it.isNotEmpty() },
genre = remoteManga.getGenres(),
thumbnailUrl = remoteManga.thumbnail_url?.takeIf { it.isNotEmpty() },
status = remoteManga.status.toLong(),
initialized = true,
),
@@ -8,7 +8,6 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@@ -119,12 +118,14 @@ data class Manga(
fun toSManga(): SManga = SManga.create().also {
it.url = url
it.title = title
it.artist = artist
it.author = author
it.description = description
it.genre = genre.orEmpty().joinToString()
it.status = status.toInt()
// SY -->
it.title = ogTitle
it.artist = ogArtist
it.author = ogAuthor
it.description = ogDescription
it.genre = ogGenre.orEmpty().joinToString()
it.status = ogStatus.toInt()
// SY <--
it.thumbnail_url = thumbnailUrl
it.initialized = initialized
}
@@ -228,19 +229,6 @@ fun Manga.toDbManga(): DbManga = MangaImpl().also {
it.initialized = initialized
}
fun Manga.toMangaInfo(): MangaInfo = MangaInfo(
// SY -->
artist = ogArtist ?: "",
author = ogAuthor ?: "",
cover = thumbnailUrl ?: "",
description = ogDescription ?: "",
genres = ogGenre ?: emptyList(),
key = url,
status = ogStatus.toInt(),
title = ogTitle,
// SY <--
)
fun Manga.toMangaUpdate(): MangaUpdate {
return MangaUpdate(
id = id,
@@ -252,12 +240,14 @@ fun Manga.toMangaUpdate(): MangaUpdate {
chapterFlags = chapterFlags,
coverLastModified = coverLastModified,
url = url,
title = title,
artist = artist,
author = author,
description = description,
genre = genre,
status = status,
// SY -->
title = ogTitle,
artist = ogArtist,
author = ogAuthor,
description = ogDescription,
genre = ogGenre,
status = ogStatus,
// SY <--
thumbnailUrl = thumbnailUrl,
initialized = initialized,
)
@@ -24,6 +24,7 @@ import androidx.compose.ui.unit.dp
import com.google.accompanist.flowlayout.FlowRow
import eu.kanade.presentation.components.SuggestionChip
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.online.all.EHentai
import exh.metadata.metadata.EHentaiSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
@@ -31,7 +32,6 @@ import exh.metadata.metadata.base.RaisedTag
import exh.source.EH_SOURCE_ID
import exh.source.EXH_SOURCE_ID
import exh.util.SourceTagsUtil
import tachiyomi.source.Source
@Immutable
data class DisplayTag(
@@ -4,7 +4,6 @@ import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
import exh.md.utils.MdUtil
import tachiyomi.source.model.MangaInfo
import eu.kanade.domain.manga.model.Manga as DomainManga
interface Manga : SManga {
@@ -84,19 +83,6 @@ interface Manga : SManga {
}
}
fun Manga.toMangaInfo(): MangaInfo {
return MangaInfo(
artist = this.artist ?: "",
author = this.author ?: "",
cover = this.thumbnail_url ?: "",
description = this.description ?: "",
genres = this.getGenres() ?: emptyList(),
key = this.url,
status = this.status,
title = this.title,
)
}
fun Manga.toDomainManga(): DomainManga? {
val mangaId = id ?: return null
return DomainManga(
@@ -21,7 +21,6 @@ import eu.kanade.domain.manga.interactor.InsertFlatMetadata
import eu.kanade.domain.manga.interactor.InsertManga
import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.domain.manga.model.toMangaInfo
import eu.kanade.domain.manga.model.toMangaUpdate
import eu.kanade.domain.track.interactor.GetTracks
import eu.kanade.domain.track.interactor.InsertTrack
@@ -34,7 +33,6 @@ import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toDomainChapter
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
import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Companion.start
@@ -51,9 +49,6 @@ import eu.kanade.tachiyomi.data.track.TrackStatus
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.source.online.all.MergedSource
import eu.kanade.tachiyomi.ui.library.LibraryGroup
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
@@ -88,7 +83,6 @@ 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
@@ -532,12 +526,10 @@ class LibraryUpdateService(
private suspend fun updateManga(manga: DomainManga, loggedServices: List<TrackService>): List<DomainChapter> {
val source = sourceManager.getOrStub(manga.source)
val mangaInfo: MangaInfo = manga.toMangaInfo()
// Update manga metadata if needed
if (preferences.autoUpdateMetadata()) {
val updatedMangaInfo = source.getMangaDetails(manga.toMangaInfo())
updateManga.awaitUpdateFromSource(manga, updatedMangaInfo, manualFetch = false, coverCache)
val networkManga = source.getMangaDetails(manga.toSManga())
updateManga.awaitUpdateFromSource(manga, networkManga, manualFetch = false, coverCache)
}
// SY -->
@@ -559,8 +551,7 @@ class LibraryUpdateService(
}
// SY <--
val chapters = source.getChapterList(mangaInfo)
.map { it.toSChapter() }
val chapters = source.getChapterList(manga.toSManga())
// Get manga from database to account for if it was removed during the update
val dbManga = getManga.await(manga.id)
@@ -592,27 +583,19 @@ class LibraryUpdateService(
progressCount,
manga,
) { mangaWithNotif ->
sourceManager.get(mangaWithNotif.source)?.let { source ->
val source = sourceManager.get(mangaWithNotif.source) ?: return@withUpdateNotification
try {
val networkManga = source.getMangaDetails(mangaWithNotif.copy())
mangaWithNotif.prepUpdateCover(coverCache, networkManga, true)
mangaWithNotif.copyFrom(networkManga)
try {
val networkManga =
source.getMangaDetails(mangaWithNotif.toMangaInfo())
val sManga = networkManga.toSManga()
mangaWithNotif.prepUpdateCover(coverCache, sManga, true)
sManga.thumbnail_url?.let {
mangaWithNotif.thumbnail_url = it
try {
updateManga.await(
mangaWithNotif.toDomainManga()!!
.toMangaUpdate(),
)
} catch (e: Exception) {
logcat(LogPriority.ERROR) { "Manga don't exist anymore" }
}
}
} catch (e: Throwable) {
// Ignore errors and continue
logcat(LogPriority.ERROR, e)
updateManga.await(mangaWithNotif.toDomainManga()!!.toMangaUpdate())
} catch (e: Exception) {
logcat(LogPriority.ERROR) { "Manga doesn't exist anymore" }
}
} catch (e: Throwable) {
// Ignore errors and continue
logcat(LogPriority.ERROR, e)
}
}
}
@@ -697,7 +680,7 @@ class LibraryUpdateService(
}
updatingManga.remove(manga)
completed.andIncrement
completed.getAndIncrement()
notifier.showProgressNotification(
updatingManga,
completed.get(),
@@ -748,7 +731,7 @@ class LibraryUpdateService(
updateManga.awaitUpdateFavorite(dbManga.id, true)
}
updateManga.awaitUpdateFromSource(dbManga, networkManga.toMangaInfo(), true)
updateManga.awaitUpdateFromSource(dbManga, networkManga, true)
metadata.mangaId = dbManga.id
insertFlatMetadata.await(metadata)
}
@@ -10,13 +10,12 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.toMangaInfo
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.lang.awaitSingle
import eu.kanade.tachiyomi.util.lang.runAsObservable
import eu.kanade.tachiyomi.util.lang.withIOContext
import exh.md.utils.FollowStatus
import exh.md.utils.MdUtil
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@@ -134,7 +133,7 @@ class MdList(private val context: Context, id: Long) : TrackService(id) {
.flatMap { page ->
runAsObservable {
page.mangas.map {
toTrackSearch(mdex.getMangaDetails(it.toMangaInfo()))
toTrackSearch(mdex.getMangaDetails(it))
}
}
}
@@ -142,11 +141,11 @@ class MdList(private val context: Context, id: Long) : TrackService(id) {
}
}
private fun toTrackSearch(mangaInfo: MangaInfo): TrackSearch = TrackSearch.create(TrackManager.MDLIST).apply {
tracking_url = MdUtil.baseUrl + mangaInfo.key
private fun toTrackSearch(mangaInfo: SManga): TrackSearch = TrackSearch.create(TrackManager.MDLIST).apply {
tracking_url = MdUtil.baseUrl + mangaInfo.url
title = mangaInfo.title
cover_url = mangaInfo.cover
summary = mangaInfo.description
cover_url = mangaInfo.thumbnail_url.orEmpty()
summary = mangaInfo.description.orEmpty()
}
override suspend fun login(username: String, password: String): Unit = throw Exception("not used")
@@ -10,10 +10,6 @@ import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toChapterInfo
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.ChapterRecognition
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
import eu.kanade.tachiyomi.util.storage.DiskUtil
@@ -27,8 +23,6 @@ import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.encodeToStream
import logcat.LogPriority
import rx.Observable
import tachiyomi.source.model.ChapterInfo
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.io.FileInputStream
@@ -125,11 +119,10 @@ class LocalSource(
// Fetch chapters of all the manga
mangas.forEach { manga ->
val mangaInfo = manga.toMangaInfo()
runBlocking {
val chapters = getChapterList(mangaInfo)
val chapters = getChapterList(manga)
if (chapters.isNotEmpty()) {
val chapter = chapters.last().toSChapter()
val chapter = chapters.last()
val format = getFormat(chapter)
if (format is Format.Epub) {
@@ -161,12 +154,37 @@ class LocalSource(
}
}
private fun SManga.toJson(): MangaJson {
return MangaJson(title, author, artist, description, genre?.split(", "), status)
private fun SManga.toJson(): MangaDetails {
return MangaDetails(title, author, artist, description, genre?.split(", "), status)
}
// SY <--
// Manga details related
override suspend fun getMangaDetails(manga: SManga): SManga {
val baseDirsFile = getBaseDirectoriesFiles(context)
getCoverFile(manga.url, baseDirsFile)?.let {
manga.thumbnail_url = it.absolutePath
}
getMangaDirsFiles(manga.url, baseDirsFile)
.firstOrNull { it.extension.equals("json", ignoreCase = true) }
?.let { file ->
json.decodeFromStream<MangaDetails>(file.inputStream()).run {
title?.let { manga.title = it }
author?.let { manga.author = it }
artist?.let { manga.artist = it }
description?.let { manga.description = it }
genre?.let { manga.genre = it.joinToString() }
status?.let { manga.status = it }
}
}
return manga
}
@Serializable
data class MangaJson(
data class MangaDetails(
val title: String? = null,
val author: String? = null,
val artist: String? = null,
@@ -174,50 +192,16 @@ class LocalSource(
val genre: List<String>? = null,
val status: Int? = null,
)
// SY <--
// Manga details related
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
var mangaInfo = manga
val baseDirsFile = getBaseDirectoriesFiles(context)
val coverFile = getCoverFile(manga.key, baseDirsFile)
coverFile?.let {
mangaInfo = mangaInfo.copy(cover = it.absolutePath)
}
val localDetails = getMangaDirsFiles(manga.key, baseDirsFile)
.firstOrNull { it.extension.equals("json", ignoreCase = true) }
if (localDetails != null) {
val mangaJson = json.decodeFromStream<MangaJson>(localDetails.inputStream())
mangaInfo = mangaInfo.copy(
title = mangaJson.title ?: mangaInfo.title,
author = mangaJson.author ?: mangaInfo.author,
artist = mangaJson.artist ?: mangaInfo.artist,
description = mangaJson.description ?: mangaInfo.description,
genres = mangaJson.genre ?: mangaInfo.genres,
status = mangaJson.status ?: mangaInfo.status,
)
}
return mangaInfo
}
// Chapters
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> {
val sManga = manga.toSManga()
override suspend fun getChapterList(manga: SManga): List<SChapter> {
val baseDirsFile = getBaseDirectoriesFiles(context)
return getMangaDirsFiles(manga.key, baseDirsFile)
return getMangaDirsFiles(manga.url, baseDirsFile)
// Only keep supported formats
.filter { it.isDirectory || isSupportedFile(it.extension) }
.map { chapterFile ->
SChapter.create().apply {
url = "${manga.key}/${chapterFile.name}"
url = "${manga.url}/${chapterFile.name}"
name = if (chapterFile.isDirectory) {
chapterFile.name
} else {
@@ -225,7 +209,7 @@ class LocalSource(
}
date_upload = chapterFile.lastModified()
chapter_number = ChapterRecognition.parseChapterNumber(sManga.title, this.name, this.chapter_number)
chapter_number = ChapterRecognition.parseChapterNumber(manga.title, this.name, this.chapter_number)
val format = getFormat(chapterFile)
if (format is Format.Epub) {
@@ -235,9 +219,8 @@ class LocalSource(
}
}
}
.map { it.toChapterInfo() }
.sortedWith { c1, c2 ->
val c = c2.number.compareTo(c1.number)
val c = c2.chapter_number.compareTo(c1.chapter_number)
if (c == 0) c2.name.compareToCaseInsensitiveNaturalOrder(c1.name) else c
}
.toList()
@@ -256,7 +239,7 @@ class LocalSource(
)
// Unused stuff
override suspend fun getPageList(chapter: ChapterInfo) = throw UnsupportedOperationException("Unused")
override suspend fun getPageList(chapter: SChapter) = throw UnsupportedOperationException("Unused")
// Miscellaneous
private fun isSupportedFile(extension: String): Boolean {
@@ -1,17 +1,17 @@
package eu.kanade.tachiyomi.source
import eu.kanade.tachiyomi.network.ProgressListener
import eu.kanade.tachiyomi.source.model.SManga
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import okhttp3.CacheControl
import okhttp3.Response
import tachiyomi.source.model.MangaInfo
interface PagePreviewSource : Source {
suspend fun getPagePreviewList(manga: MangaInfo, page: Int): PagePreviewPage
suspend fun getPagePreviewList(manga: SManga, page: Int): PagePreviewPage
suspend fun fetchPreviewImage(page: PagePreviewInfo, cacheControl: CacheControl? = null): Response
}
@@ -7,35 +7,28 @@ import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toChapterInfo
import eu.kanade.tachiyomi.source.model.toMangaInfo
import eu.kanade.tachiyomi.source.model.toPageUrl
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.ui.manga.MergedMangaData
import eu.kanade.tachiyomi.util.lang.awaitSingle
import rx.Observable
import tachiyomi.source.model.ChapterInfo
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
/**
* A basic interface for creating a source. It could be an online source, a local source, etc...
*/
interface Source : tachiyomi.source.Source {
interface Source {
/**
* Id for the source. Must be unique.
*/
override val id: Long
val id: Long
/**
* Name of the source.
*/
override val name: String
val name: String
override val lang: String
val lang: String
get() = ""
/**
@@ -76,29 +69,24 @@ interface Source : tachiyomi.source.Source {
* [1.x API] Get the updated details for a manga.
*/
@Suppress("DEPRECATION")
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
val sManga = manga.toSManga()
val networkManga = fetchMangaDetails(sManga).awaitSingle()
sManga.copyFrom(networkManga)
return sManga.toMangaInfo()
suspend fun getMangaDetails(manga: SManga): SManga {
return fetchMangaDetails(manga).awaitSingle()
}
/**
* [1.x API] Get all the available chapters for a manga.
*/
@Suppress("DEPRECATION")
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> {
return fetchChapterList(manga.toSManga()).awaitSingle()
.map { it.toChapterInfo() }
suspend fun getChapterList(manga: SManga): List<SChapter> {
return fetchChapterList(manga).awaitSingle()
}
/**
* [1.x API] Get the list of pages a chapter has.
*/
@Suppress("DEPRECATION")
override suspend fun getPageList(chapter: ChapterInfo): List<tachiyomi.source.model.Page> {
return fetchPageList(chapter.toSChapter()).awaitSingle()
.map { it.toPageUrl() }
suspend fun getPageList(chapter: SChapter): List<Page> {
return fetchPageList(chapter).awaitSingle()
}
}
@@ -45,8 +45,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import rx.Observable
import tachiyomi.source.model.ChapterInfo
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.injectLazy
import kotlin.reflect.KClass
@@ -208,7 +206,7 @@ class SourceManager(
override val lang: String = sourceData.lang
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
override suspend fun getMangaDetails(manga: SManga): SManga {
throw getSourceNotInstalledException()
}
@@ -216,7 +214,7 @@ class SourceManager(
return Observable.error(getSourceNotInstalledException())
}
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> {
override suspend fun getChapterList(manga: SManga): List<SChapter> {
throw getSourceNotInstalledException()
}
@@ -224,7 +222,7 @@ class SourceManager(
return Observable.error(getSourceNotInstalledException())
}
override suspend fun getPageList(chapter: ChapterInfo): List<tachiyomi.source.model.Page> {
override suspend fun getPageList(chapter: SChapter): List<Page> {
throw getSourceNotInstalledException()
}
@@ -5,7 +5,6 @@ import eu.kanade.tachiyomi.network.ProgressListener
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import rx.subjects.Subject
import tachiyomi.source.model.PageUrl
@Serializable
open class Page(
@@ -66,16 +65,3 @@ open class Page(
const val ERROR = 4
}
}
fun Page.toPageUrl(): PageUrl {
return PageUrl(
url = this.imageUrl ?: this.url,
)
}
fun PageUrl.toPage(index: Int): Page {
return Page(
index = index,
imageUrl = this.url,
)
}
@@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.source.model
import data.Chapters
import tachiyomi.source.model.ChapterInfo
import java.io.Serializable
interface SChapter : Serializable {
@@ -36,26 +35,23 @@ interface SChapter : Serializable {
fun create(): SChapter {
return SChapterImpl()
}
}
}
fun SChapter.toChapterInfo(): ChapterInfo {
return ChapterInfo(
dateUpload = this.date_upload,
key = this.url,
name = this.name,
number = this.chapter_number,
scanlator = this.scanlator ?: "",
)
}
fun ChapterInfo.toSChapter(): SChapter {
val chapter = this
return SChapter.create().apply {
url = chapter.key
name = chapter.name
date_upload = chapter.dateUpload
chapter_number = chapter.number
scanlator = chapter.scanlator
// SY -->
operator fun invoke(
name: String,
url: String,
date_upload: Long = 0,
chapter_number: Float = -1F,
scanlator: String? = null,
): SChapter {
return create().apply {
this.name = name
this.url = url
this.date_upload = date_upload
this.chapter_number = chapter_number
this.scanlator = scanlator
}
}
// SY <--
}
}
@@ -4,7 +4,6 @@ import data.Mangas
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.download.DownloadManager
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.Serializable
@@ -127,6 +126,20 @@ interface SManga : Serializable {
}
}
fun copy() = create().also {
it.url = url
// SY -->
it.title = originalTitle
it.artist = originalArtist
it.author = originalAuthor
it.description = originalDescription
it.genre = originalGenre
it.status = originalStatus
// SY <--
it.thumbnail_url = thumbnail_url
it.initialized = initialized
}
companion object {
const val UNKNOWN = 0
const val ONGOING = 1
@@ -139,32 +152,55 @@ interface SManga : Serializable {
fun create(): SManga {
return SMangaImpl()
}
// SY -->
operator fun invoke(
url: String,
title: String,
artist: String? = null,
author: String? = null,
description: String? = null,
genre: String? = null,
status: Int = 0,
thumbnail_url: String? = null,
initialized: Boolean = false,
): SManga {
return create().also {
it.url = url
it.title = title
it.artist = artist
it.author = author
it.description = description
it.genre = genre
it.status = status
it.thumbnail_url = thumbnail_url
it.initialized = initialized
}
}
// SY <--
}
}
fun SManga.toMangaInfo(): MangaInfo {
return MangaInfo(
key = this.url,
title = this.title,
artist = this.artist ?: "",
author = this.author ?: "",
description = this.description ?: "",
genres = this.getGenres() ?: emptyList(),
status = this.status,
cover = this.thumbnail_url ?: "",
)
}
fun MangaInfo.toSManga(): SManga {
val mangaInfo = this
return SManga.create().apply {
url = mangaInfo.key
title = mangaInfo.title
artist = mangaInfo.artist
author = mangaInfo.author
description = mangaInfo.description
genre = mangaInfo.genres.joinToString(", ")
status = mangaInfo.status
thumbnail_url = mangaInfo.cover
}
// SY -->
fun SManga.copy(
url: String = this.url,
title: String = this.originalTitle,
artist: String? = this.originalArtist,
author: String? = this.originalAuthor,
description: String? = this.originalDescription,
genre: String? = this.originalGenre,
status: Int = this.status,
thumbnail_url: String? = this.thumbnail_url,
initialized: Boolean = this.initialized,
) = SManga.create().also {
it.url = url
it.title = title
it.artist = artist
it.author = author
it.description = description
it.genre = genre
it.status = status
it.thumbnail_url = thumbnail_url
it.initialized = initialized
}
// SY <--
@@ -6,14 +6,12 @@ import eu.kanade.domain.manga.interactor.GetManga
import eu.kanade.domain.manga.interactor.InsertFlatMetadata
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toMangaInfo
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
import eu.kanade.tachiyomi.util.lang.awaitSingle
import eu.kanade.tachiyomi.util.lang.runAsObservable
import exh.metadata.metadata.base.RaisedSearchMetadata
import rx.Completable
import rx.Single
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.reflect.KClass
@@ -51,11 +49,11 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
*/
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("Use the MangaInfo variant")
fun parseToManga(manga: SManga, input: I): Completable = runAsObservable {
parseToManga(manga.toMangaInfo(), input)
fun parseToMangaCompletable(manga: SManga, input: I): Completable = runAsObservable {
parseToManga(manga, input)
}.toCompletable()
suspend fun parseToManga(manga: MangaInfo, input: I): MangaInfo {
suspend fun parseToManga(manga: SManga, input: I): SManga {
val mangaId = manga.id()
val metadata = if (mangaId != null) {
val flatMetadata = getFlatMetadataById.await(mangaId)
@@ -114,5 +112,5 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
@Composable
fun DescriptionComposable(state: MangaScreenState.Success, openMetadataViewer: () -> Unit, search: (String) -> Unit)
suspend fun MangaInfo.id() = getManga.await(key, id)?.id
suspend fun SManga.id() = getManga.await(url, id)?.id
}
@@ -1,6 +1,6 @@
package eu.kanade.tachiyomi.source.online
import tachiyomi.source.Source
import eu.kanade.tachiyomi.source.Source
interface RandomMangaSource : Source {
suspend fun fetchRandomMangaUrl(): String
@@ -23,9 +23,7 @@ import eu.kanade.tachiyomi.source.model.MetadataMangasPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
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.source.model.copy
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.NamespaceSource
@@ -92,8 +90,6 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.nodes.TextNode
import rx.Observable
import tachiyomi.source.model.ChapterInfo
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.injectLazy
import java.io.ByteArrayOutputStream
import java.io.IOException
@@ -306,13 +302,13 @@ class EHentai(
MetadataMangasPage(mangaFromSource.first.map { it.manga }, mangaFromSource.second, mangaFromSource.first.map { it.metadata })
}
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> = getChapterList(manga) {}
override suspend fun getChapterList(manga: SManga): List<SChapter> = getChapterList(manga) {}
suspend fun getChapterList(manga: MangaInfo, throttleFunc: suspend () -> Unit): List<ChapterInfo> {
suspend fun getChapterList(manga: SManga, throttleFunc: suspend () -> Unit): List<SChapter> {
// Pull all the way to the root gallery
// We can't do this with RxJava or we run into stack overflows on shit like this:
// https://exhentai.org/g/1073061/f9345f1c12/
var url = manga.key
var url = manga.url
var doc: Document
while (true) {
@@ -348,11 +344,11 @@ class EHentai(
}
val newDisplay = doc.select("#gnd a")
// Build chapter for root gallery
val self = ChapterInfo(
key = EHentaiSearchMetadata.normalizeUrl(doc.location()),
val self = SChapter(
url = EHentaiSearchMetadata.normalizeUrl(doc.location()),
name = "v1: " + doc.selectFirst("#gn")!!.text(),
number = 1f,
dateUpload = MetadataUtil.EX_DATE_FORMAT.parse(
chapter_number = 1f,
date_upload = MetadataUtil.EX_DATE_FORMAT.parse(
doc.select("#gdd .gdt1").find { el ->
el.text().lowercase() == "posted:"
}!!.nextElementSibling()!!.text(),
@@ -366,26 +362,28 @@ class EHentai(
val link = newGallery.attr("href")
val name = newGallery.text()
val posted = (newGallery.nextSibling() as TextNode).text().removePrefix(", added ")
ChapterInfo(
key = EHentaiSearchMetadata.normalizeUrl(link),
SChapter(
url = EHentaiSearchMetadata.normalizeUrl(link),
name = "v${index + 2}: $name",
number = index + 2f,
dateUpload = MetadataUtil.EX_DATE_FORMAT.parse(posted)!!.time,
chapter_number = index + 2f,
date_upload = MetadataUtil.EX_DATE_FORMAT.parse(posted)!!.time,
)
}.reversed() + self
}
}
@Suppress("OverridingDeprecatedMember", "DEPRECATION")
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getChapterList"))
@Suppress("DEPRECATION")
override fun fetchChapterList(manga: SManga) = fetchChapterList(manga) {}
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("Use getChapterList instead")
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getChapterList"))
fun fetchChapterList(manga: SManga, throttleFunc: suspend () -> Unit) = runAsObservable {
getChapterList(manga.toMangaInfo(), throttleFunc).map { it.toSChapter() }
getChapterList(manga, throttleFunc)
}
override fun fetchPageList(chapter: SChapter) = fetchChapterPage(chapter, baseUrl + chapter.url)
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getPageList"))
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> = fetchChapterPage(chapter, baseUrl + chapter.url)
.map {
it.mapIndexed { i, s ->
Page(i, s)
@@ -541,6 +539,7 @@ class EHentai(
*
* @param manga the manga to be updated.
*/
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getMangaDetails"))
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
return client.newCall(mangaDetailsRequest(manga))
.asObservableWithAsyncStacktrace()
@@ -556,7 +555,8 @@ class EHentai(
} else Observable.just(doc)
pre.flatMap {
parseToManga(manga, it).andThen(
@Suppress("DEPRECATION")
parseToMangaCompletable(manga, it).andThen(
Observable.just(
manga.apply {
initialized = true
@@ -576,17 +576,17 @@ class EHentai(
}
}
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
override suspend fun getMangaDetails(manga: SManga): SManga {
val exception = Exception("Async stacktrace")
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).awaitResponse()
val response = client.newCall(mangaDetailsRequest(manga)).awaitResponse()
if (response.isSuccessful) {
// Pull to most recent
val doc = response.asJsoup()
val newerGallery = doc.select("#gnd a").lastOrNull()
val pre = if (newerGallery != null && DebugToggles.PULL_TO_ROOT_WHEN_LOADING_EXH_MANGA_DETAILS.enabled) {
val sManga = manga.toSManga().apply {
url = EHentaiSearchMetadata.normalizeUrl(newerGallery.attr("href"))
}
val sManga = manga.copy(
url = EHentaiSearchMetadata.normalizeUrl(newerGallery.attr("href")),
)
client.newCall(mangaDetailsRequest(sManga)).await().asJsoup()
} else doc
return parseToManga(manga, pre)
@@ -1097,12 +1097,12 @@ class EHentai(
}
override suspend fun getPagePreviewList(
manga: MangaInfo,
manga: SManga,
page: Int,
): PagePreviewPage {
val doc = client.newCall(
exGet(
(baseUrl + manga.key)
(baseUrl + manga.url)
.toHttpUrl()
.newBuilder()
.removeAllQueryParameters("nw")
@@ -6,7 +6,7 @@ import android.os.Build
import androidx.compose.runtime.Composable
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.NamespaceSource
@@ -20,7 +20,6 @@ import exh.source.DelegatedHttpSource
import exh.ui.metadata.adapters.HitomiDescription
import exh.util.urlImportFetchSearchManga
import org.jsoup.nodes.Document
import tachiyomi.source.model.MangaInfo
import java.text.SimpleDateFormat
import java.util.Locale
@@ -38,8 +37,8 @@ class Hitomi(delegate: HttpSource, val context: Context) :
super.fetchSearchManga(page, query, filters)
}
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
override suspend fun getMangaDetails(manga: SManga): SManga {
val response = client.newCall(mangaDetailsRequest(manga)).await()
return parseToManga(manga, response.asJsoup())
}
@@ -14,7 +14,6 @@ import eu.kanade.tachiyomi.source.model.MetadataMangasPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toChapterInfo
import eu.kanade.tachiyomi.source.online.BrowseSourceFilterHeader
import eu.kanade.tachiyomi.source.online.FollowsSource
import eu.kanade.tachiyomi.source.online.HttpSource
@@ -54,8 +53,6 @@ import exh.ui.metadata.adapters.MangaDexDescription
import okhttp3.OkHttpClient
import okhttp3.Response
import rx.Observable
import tachiyomi.source.model.ChapterInfo
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.reflect.KClass
@@ -182,24 +179,27 @@ class MangaDex(delegate: HttpSource, val context: Context) :
}
}
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getMangaDetails"))
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
return mangaHandler.fetchMangaDetailsObservable(manga, id)
}
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
override suspend fun getMangaDetails(manga: SManga): SManga {
return mangaHandler.getMangaDetails(manga, id)
}
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getChapterList"))
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
return mangaHandler.fetchChapterListObservable(manga, blockedGroups(), blockedUploaders())
}
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> {
override suspend fun getChapterList(manga: SManga): List<SChapter> {
return mangaHandler.getChapterList(manga, blockedGroups(), blockedUploaders())
}
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getPageList"))
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
return runAsObservable { pageHandler.fetchPageList(chapter.toChapterInfo(), isLogged(), usePort443Only(), dataSaver(), delegate) }
return runAsObservable { pageHandler.fetchPageList(chapter, isLogged(), usePort443Only(), dataSaver(), delegate) }
}
override fun fetchImage(page: Page): Observable<Response> {
@@ -301,11 +301,11 @@ class MangaDex(delegate: HttpSource, val context: Context) :
return mangaHandler.fetchRandomMangaId()
}
suspend fun getMangaSimilar(manga: MangaInfo): MetadataMangasPage {
suspend fun getMangaSimilar(manga: SManga): MetadataMangasPage {
return similarHandler.getSimilar(manga)
}
suspend fun getMangaRelated(manga: MangaInfo): MetadataMangasPage {
suspend fun getMangaRelated(manga: SManga): MetadataMangasPage {
return similarHandler.getRelated(manga)
}
@@ -10,7 +10,6 @@ import eu.kanade.domain.manga.interactor.GetMergedReferencesById
import eu.kanade.domain.manga.interactor.InsertManga
import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.toMangaInfo
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.Source
@@ -19,7 +18,7 @@ import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.model.copy
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
@@ -33,8 +32,6 @@ import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import okhttp3.Response
import tachiyomi.source.model.ChapterInfo
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@@ -64,18 +61,20 @@ class MergedSource : HttpSource() {
override fun chapterListParse(response: Response) = throw UnsupportedOperationException()
override fun pageListParse(response: Response) = throw UnsupportedOperationException()
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getChapterList"))
override fun fetchChapterList(manga: SManga) = throw UnsupportedOperationException()
override suspend fun getChapterList(manga: MangaInfo) = throw UnsupportedOperationException()
override suspend fun getChapterList(manga: SManga) = throw UnsupportedOperationException()
override fun fetchImage(page: Page) = throw UnsupportedOperationException()
override fun fetchImageUrl(page: Page) = throw UnsupportedOperationException()
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getPageList"))
override fun fetchPageList(chapter: SChapter) = throw UnsupportedOperationException()
override suspend fun getPageList(chapter: ChapterInfo) = throw UnsupportedOperationException()
override suspend fun getPageList(chapter: SChapter) = throw UnsupportedOperationException()
override fun fetchLatestUpdates(page: Int) = throw UnsupportedOperationException()
override fun fetchPopularManga(page: Int) = throw UnsupportedOperationException()
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
override suspend fun getMangaDetails(manga: SManga): SManga {
return withIOContext {
val mergedManga = getManga.await(manga.key, id) ?: throw Exception("merged manga not in db")
val mergedManga = getManga.await(manga.url, id) ?: throw Exception("merged manga not in db")
val mangaReferences = getMergedReferencesById.await(mergedManga.id)
.apply {
if (isEmpty()) {
@@ -93,10 +92,10 @@ class MergedSource : HttpSource() {
val mangaInfoReference = mangaReferences.firstOrNull { it.isInfoManga }
?: mangaReferences.firstOrNull { it.mangaId != it.mergeId }
val dbManga = mangaInfoReference?.run {
getManga.await(mangaUrl, mangaSourceId)?.toMangaInfo()
getManga.await(mangaUrl, mangaSourceId)?.toSManga()
}
(dbManga ?: mergedManga.toMangaInfo()).copy(
key = manga.key,
(dbManga ?: mergedManga.toSManga()).copy(
url = manga.url,
)
}
}
@@ -185,8 +184,7 @@ class MergedSource : HttpSource() {
val (source, loadedManga, reference) =
it.load(sourceManager, getManga, insertManga, updateManga)
if (loadedManga != null && reference.getChapterUpdates) {
val chapterList = source.getChapterList(loadedManga.toMangaInfo())
.map(ChapterInfo::toSChapter)
val chapterList = source.getChapterList(loadedManga.toSManga())
val results =
syncChaptersWithSource.await(chapterList, loadedManga, source)
if (ifDownloadNewChapters && reference.downloadChapters) {
@@ -226,7 +224,7 @@ class MergedSource : HttpSource() {
),
)!!
val newManga = getManga.await(id)!!
updateManga.awaitUpdateFromSource(newManga, source.getMangaDetails(newManga.toMangaInfo()), false)
updateManga.awaitUpdateFromSource(newManga, source.getMangaDetails(newManga.toSManga()), false)
manga = getManga.await(id)!!
}
return LoadedMangaSource(source, manga, this)
@@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.source.PagePreviewInfo
import eu.kanade.tachiyomi.source.PagePreviewPage
import eu.kanade.tachiyomi.source.PagePreviewSource
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.NamespaceSource
@@ -30,7 +30,6 @@ import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.CacheControl
import okhttp3.Response
import tachiyomi.source.model.MangaInfo
class NHentai(delegate: HttpSource, val context: Context) :
DelegatedHttpSource(delegate),
@@ -57,8 +56,8 @@ class NHentai(delegate: HttpSource, val context: Context) :
super.fetchSearchManga(page, query, filters)
}
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
override suspend fun getMangaDetails(manga: SManga): SManga {
val response = client.newCall(mangaDetailsRequest(manga)).await()
return parseToManga(manga, response)
}
@@ -181,9 +180,9 @@ class NHentai(delegate: HttpSource, val context: Context) :
NHentaiDescription(state, openMetadataViewer)
}
override suspend fun getPagePreviewList(manga: MangaInfo, page: Int): PagePreviewPage {
override suspend fun getPagePreviewList(manga: SManga, page: Int): PagePreviewPage {
val metadata = fetchOrLoadMetadata(manga.id()) {
client.newCall(mangaDetailsRequest(manga.toSManga())).await()
client.newCall(mangaDetailsRequest(manga)).await()
}
return PagePreviewPage(
page,
@@ -6,7 +6,7 @@ import androidx.compose.runtime.Composable
import androidx.core.net.toUri
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.UrlImportableSource
@@ -21,7 +21,6 @@ import exh.util.urlImportFetchSearchManga
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.nodes.TextNode
import tachiyomi.source.model.MangaInfo
class PervEden(delegate: HttpSource, val context: Context) :
DelegatedHttpSource(delegate),
@@ -36,8 +35,8 @@ class PervEden(delegate: HttpSource, val context: Context) :
super.fetchSearchManga(page, query, filters)
}
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
override suspend fun getMangaDetails(manga: SManga): SManga {
val response = client.newCall(mangaDetailsRequest(manga)).await()
return parseToManga(manga, response.asJsoup())
}
@@ -6,7 +6,7 @@ import androidx.compose.runtime.Composable
import androidx.core.net.toUri
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.NamespaceSource
@@ -20,7 +20,6 @@ import exh.ui.metadata.adapters.EightMusesDescription
import exh.util.urlImportFetchSearchManga
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import tachiyomi.source.model.MangaInfo
class EightMuses(delegate: HttpSource, val context: Context) :
DelegatedHttpSource(delegate),
@@ -36,8 +35,8 @@ class EightMuses(delegate: HttpSource, val context: Context) :
super.fetchSearchManga(page, query, filters)
}
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
override suspend fun getMangaDetails(manga: SManga): SManga {
val response = client.newCall(mangaDetailsRequest(manga)).await()
return parseToManga(manga, response.asJsoup())
}
@@ -5,7 +5,7 @@ import android.net.Uri
import androidx.compose.runtime.Composable
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.NamespaceSource
@@ -19,7 +19,6 @@ import exh.ui.metadata.adapters.HBrowseDescription
import exh.util.urlImportFetchSearchManga
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import tachiyomi.source.model.MangaInfo
class HBrowse(delegate: HttpSource, val context: Context) :
DelegatedHttpSource(delegate),
@@ -35,8 +34,8 @@ class HBrowse(delegate: HttpSource, val context: Context) :
super.fetchSearchManga(page, query, filters)
}
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
override suspend fun getMangaDetails(manga: SManga): SManga {
val response = client.newCall(mangaDetailsRequest(manga)).await()
return parseToManga(manga, response.asJsoup())
}
@@ -7,7 +7,7 @@ import androidx.core.net.toUri
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.NamespaceSource
@@ -24,7 +24,6 @@ import exh.util.trimAll
import exh.util.urlImportFetchSearchManga
import org.jsoup.nodes.Document
import rx.Observable
import tachiyomi.source.model.MangaInfo
class Pururin(delegate: HttpSource, val context: Context) :
DelegatedHttpSource(delegate),
@@ -53,8 +52,8 @@ class Pururin(delegate: HttpSource, val context: Context) :
}
}
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
override suspend fun getMangaDetails(manga: SManga): SManga {
val response = client.newCall(mangaDetailsRequest(manga)).await()
return parseToManga(manga, response.asJsoup())
}
@@ -6,7 +6,7 @@ import androidx.compose.runtime.Composable
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.NamespaceSource
@@ -24,7 +24,6 @@ import exh.util.trimAll
import exh.util.urlImportFetchSearchManga
import org.jsoup.nodes.Document
import rx.Observable
import tachiyomi.source.model.MangaInfo
import java.text.SimpleDateFormat
import java.util.Locale
@@ -50,8 +49,8 @@ class Tsumino(delegate: HttpSource, val context: Context) :
return "https://tsumino.com/Book/Info/${uri.lastPathSegment}"
}
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
val response = client.newCall(mangaDetailsRequest(manga.toSManga())).await()
override suspend fun getMangaDetails(manga: SManga): SManga {
val response = client.newCall(mangaDetailsRequest(manga)).await()
return parseToManga(manga, response.asJsoup())
}
@@ -14,7 +14,6 @@ import eu.kanade.domain.source.interactor.GetSavedSearchGlobalFeed
import eu.kanade.domain.source.interactor.InsertFeedSavedSearch
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.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source
@@ -22,7 +21,6 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.runAsObservable
@@ -272,8 +270,8 @@ open class FeedPresenter(
*/
private fun getMangaDetailsObservable(manga: Manga, source: Source): Observable<Manga> {
return runAsObservable {
val networkManga = source.getMangaDetails(manga.toMangaInfo())
manga.copyFrom(networkManga.toSManga())
val networkManga = source.getMangaDetails(manga.copy())
manga.copyFrom(networkManga)
manga.initialized = true
updateManga.await(manga.toDomainManga()!!.toMangaUpdate())
manga
@@ -20,14 +20,12 @@ import eu.kanade.domain.manga.interactor.GetManga
import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.domain.manga.model.toMangaInfo
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.MigrationListControllerBinding
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.online.all.EHentai
import eu.kanade.tachiyomi.ui.base.changehandler.OneWayFadeChangeHandler
import eu.kanade.tachiyomi.ui.base.controller.BaseController
@@ -186,13 +184,13 @@ class MigrationListController(bundle: Bundle? = null) :
)
val chapters = if (source is EHentai) {
source.getChapterList(localManga.toMangaInfo(), throttleManager::throttle)
source.getChapterList(localManga.toSManga(), throttleManager::throttle)
} else {
source.getChapterList(localManga.toMangaInfo())
source.getChapterList(localManga.toSManga())
}
try {
syncChaptersWithSource.await(chapters.map { it.toSChapter() }, localManga, source)
syncChaptersWithSource.await(chapters, localManga, source)
} catch (e: Exception) {
return@async2 null
}
@@ -223,10 +221,10 @@ class MigrationListController(bundle: Bundle? = null) :
val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id)
val chapters = try {
if (source is EHentai) {
source.getChapterList(localManga.toMangaInfo(), throttleManager::throttle)
source.getChapterList(localManga.toSManga(), throttleManager::throttle)
} else {
source.getChapterList(localManga.toMangaInfo())
}.map { it.toSChapter() }
source.getChapterList(localManga.toSManga())
}
} catch (e: Exception) {
this@MigrationListController.logcat(LogPriority.ERROR, e)
emptyList()
@@ -254,7 +252,7 @@ class MigrationListController(bundle: Bundle? = null) :
if (result != null && result.thumbnailUrl == null) {
try {
val newManga = sourceManager.getOrStub(result.source).getMangaDetails(result.toMangaInfo())
val newManga = sourceManager.getOrStub(result.source).getMangaDetails(result.toSManga())
updateManga.awaitUpdateFromSource(result, newManga, true)
} catch (e: CancellationException) {
// Ignore cancellations
@@ -359,8 +357,7 @@ class MigrationListController(bundle: Bundle? = null) :
val result = CoroutineScope(migratingManga.manga.migrationJob).async {
val localManga = smartSearchEngine.networkToLocalManga(manga.toDbManga(), source.id)
try {
val chapters = source.getChapterList(localManga.toMangaInfo())
.map { it.toSChapter() }
val chapters = source.getChapterList(localManga.toSManga())
syncChaptersWithSource.await(chapters, localManga, source)
} catch (e: Exception) {
return@async null
@@ -370,7 +367,7 @@ class MigrationListController(bundle: Bundle? = null) :
if (result != null) {
try {
val newManga = sourceManager.getOrStub(result.source).getMangaDetails(result.toMangaInfo())
val newManga = sourceManager.getOrStub(result.source).getMangaDetails(result.toSManga())
updateManga.awaitUpdateFromSource(result, newManga, true)
} catch (e: CancellationException) {
// Ignore cancellations
@@ -20,7 +20,6 @@ import eu.kanade.domain.track.model.toDomainTrack
import eu.kanade.tachiyomi.data.cache.CoverCache
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.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
import eu.kanade.tachiyomi.data.track.TrackManager
@@ -30,7 +29,6 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.browse.source.filter.AutoComplete
import eu.kanade.tachiyomi.ui.browse.source.filter.AutoCompleteSectionItem
@@ -331,8 +329,8 @@ open class BrowseSourcePresenter(
*/
private suspend fun getMangaDetails(manga: Manga): Manga {
try {
val networkManga = source.getMangaDetails(manga.toMangaInfo())
manga.copyFrom(networkManga.toSManga())
val networkManga = source.getMangaDetails(manga.copy())
manga.copyFrom(networkManga)
manga.initialized = true
updateManga.await(
manga
@@ -16,14 +16,12 @@ import eu.kanade.domain.source.interactor.GetSavedSearchBySourceIdFeed
import eu.kanade.domain.source.interactor.InsertFeedSavedSearch
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.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter.Companion.toItems
import eu.kanade.tachiyomi.util.lang.launchIO
@@ -289,8 +287,8 @@ open class SourceFeedPresenter(
*/
private fun getMangaDetailsObservable(manga: Manga, source: Source): Observable<Manga> {
return runAsObservable {
val networkManga = source.getMangaDetails(manga.toMangaInfo())
manga.copyFrom(networkManga.toSManga())
val networkManga = source.getMangaDetails(manga.copy())
manga.copyFrom(networkManga)
manga.initialized = true
updateManga.await(manga.toDomainManga()!!.toMangaUpdate())
manga
@@ -8,7 +8,6 @@ import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.domain.manga.model.toMangaUpdate
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.preference.PreferencesHelper
import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.source.CatalogueSource
@@ -16,7 +15,6 @@ import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
import eu.kanade.tachiyomi.util.lang.runAsObservable
@@ -247,8 +245,8 @@ open class GlobalSearchPresenter(
* @return The initialized manga.
*/
private suspend fun getMangaDetails(manga: Manga, source: Source): Manga {
val networkManga = source.getMangaDetails(manga.toMangaInfo())
manga.copyFrom(networkManga.toSManga())
val networkManga = source.getMangaDetails(manga.copy())
manga.copyFrom(networkManga)
manga.initialized = true
updateManga.await(manga.toDomainManga()!!.toMangaUpdate())
return manga
@@ -35,7 +35,6 @@ import eu.kanade.domain.manga.model.PagePreview
import eu.kanade.domain.manga.model.TriStateFilter
import eu.kanade.domain.manga.model.isLocal
import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.domain.manga.model.toMangaInfo
import eu.kanade.domain.track.interactor.DeleteTrack
import eu.kanade.domain.track.interactor.GetTracks
import eu.kanade.domain.track.interactor.InsertTrack
@@ -55,7 +54,6 @@ import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.PagePreviewSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.all.MergedSource
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
@@ -416,7 +414,7 @@ class MangaPresenter(
updateSuccessState { it.copy(isRefreshingInfo = true) }
try {
successState?.let {
val networkManga = it.source.getMangaDetails(it.manga.toMangaInfo())
val networkManga = it.source.getMangaDetails(it.manga.toSManga())
updateManga.awaitUpdateFromSource(it.manga, networkManga, manualFetch)
}
} catch (e: Throwable) {
@@ -964,8 +962,7 @@ class MangaPresenter(
try {
successState?.let { successState ->
if (successState.source !is MergedSource) {
val chapters = successState.source.getChapterList(successState.manga.toMangaInfo())
.map { it.toSChapter() }
val chapters = successState.source.getChapterList(successState.manga.toSManga())
val newChapters = syncChaptersWithSource.await(
chapters,
@@ -29,11 +29,12 @@ fun Manga.prepUpdateCover(coverCache: CoverCache, remoteManga: SManga, refreshSa
if (!refreshSameUrl && thumbnail_url == newUrl) return
val domainManga = toDomainManga()!!
when {
toDomainManga()!!.isLocal() -> {
domainManga.isLocal() -> {
cover_last_modified = Date().time
}
toDomainManga()!!.hasCustomCover(coverCache) -> {
domainManga.hasCustomCover(coverCache) -> {
coverCache.deleteFromCache(this, false)
}
else -> {