Show Mangadex relations in Mangadex similar

This commit is contained in:
Jobobby04 2021-12-27 16:12:09 -05:00
parent 87d9512b1f
commit 77f5acf2dd
11 changed files with 156 additions and 8 deletions

View File

@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.mdlist.MdList
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.MangasPage
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
@ -284,10 +285,14 @@ class MangaDex(delegate: HttpSource, val context: Context) :
return mangaHandler.fetchRandomMangaId()
}
suspend fun getMangaSimilar(manga: MangaInfo): MangasPage {
suspend fun getMangaSimilar(manga: MangaInfo): MetadataMangasPage {
return similarHandler.getSimilar(manga)
}
suspend fun getMangaRelated(manga: MangaInfo): MetadataMangasPage {
return similarHandler.getRelated(manga)
}
companion object {
private const val dataSaverPref = "dataSaverV5"

View File

@ -61,6 +61,10 @@ class SourceComfortableGridHolder(private val view: View, private val adapter: F
binding.badges.localText.text = itemView.context.resources.getStringArray(R.array.md_follows_options).asList()[it]
binding.badges.localText.isVisible = true
}
metadata.relation?.let {
binding.badges.localText.setText(it.resId)
binding.badges.localText.isVisible = true
}
}
}
// SY <--

View File

@ -58,6 +58,10 @@ open class SourceCompactGridHolder(private val view: View, private val adapter:
binding.badges.localText.text = itemView.context.resources.getStringArray(R.array.md_follows_options).asList()[it]
binding.badges.localText.isVisible = true
}
metadata.relation?.let {
binding.badges.localText.setText(it.resId)
binding.badges.localText.isVisible = true
}
}
}
// SY <--

View File

@ -58,6 +58,10 @@ class SourceListHolder(private val view: View, adapter: FlexibleAdapter<*>) :
binding.localText.text = itemView.context.resources.getStringArray(R.array.md_follows_options).asList()[it]
binding.localText.isVisible = true
}
metadata.relation?.let {
binding.localText.setText(it.resId)
binding.localText.isVisible = true
}
}
}
// SY <--

View File

@ -18,3 +18,25 @@ data class SimilarMangaMatchListDto(
val contentRating: String,
val score: Double,
)
@Serializable
data class RelationListDto(
val response: String,
val data: List<RelationDto>,
)
@Serializable
data class RelationDto(
val attributes: RelationAttributesDto,
val relationships: List<RelationMangaDto>,
)
@Serializable
data class RelationMangaDto(
val id: String
)
@Serializable
data class RelationAttributesDto(
val relation: String,
)

View File

@ -1,11 +1,15 @@
package exh.md.handlers
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.MetadataMangasPage
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.util.lang.withIOContext
import exh.md.dto.RelationListDto
import exh.md.dto.SimilarMangaDto
import exh.md.service.MangaDexService
import exh.md.service.SimilarService
import exh.md.utils.MangaDexRelation
import exh.md.utils.MdUtil
import exh.metadata.metadata.MangaDexSearchMetadata
import tachiyomi.source.model.MangaInfo
class SimilarHandler(
@ -14,14 +18,14 @@ class SimilarHandler(
private val similarService: SimilarService
) {
suspend fun getSimilar(manga: MangaInfo): MangasPage {
val similarDto = similarService.getSimilarManga(MdUtil.getMangaId(manga.key))
suspend fun getSimilar(manga: MangaInfo): MetadataMangasPage {
val similarDto = withIOContext { similarService.getSimilarManga(MdUtil.getMangaId(manga.key)) }
return similarDtoToMangaListPage(similarDto)
}
private suspend fun similarDtoToMangaListPage(
similarMangaDto: SimilarMangaDto,
): MangasPage {
): MetadataMangasPage {
val ids = similarMangaDto.matches.map {
it.id
}
@ -30,6 +34,34 @@ class SimilarHandler(
MdUtil.createMangaEntry(it, lang).toSManga()
}
return MangasPage(mangaList, false)
return MetadataMangasPage(mangaList, false, List(mangaList.size) { MangaDexSearchMetadata().also { it.relation = MangaDexRelation.SIMILAR } })
}
suspend fun getRelated(manga: MangaInfo): MetadataMangasPage {
val relatedListDto = withIOContext { service.relatedManga(MdUtil.getMangaId(manga.key)) }
return relatedDtoToMangaListPage(relatedListDto)
}
private suspend fun relatedDtoToMangaListPage(
relatedListDto: RelationListDto,
): MetadataMangasPage {
val ids = relatedListDto.data
.mapNotNull { it.relationships.firstOrNull() }
.map { it.id }
val mangaList = service.viewMangas(ids).data.map {
MdUtil.createMangaEntry(it, lang).toSManga()
}
return MetadataMangasPage(
mangas = mangaList,
hasNextPage = false,
mangasMetadata = mangaList.map { manga ->
MangaDexSearchMetadata().also {
it.relation = relatedListDto.data.firstOrNull { it.relationships.any { it.id == MdUtil.getMangaId(manga.url) } }
?.attributes?.relation?.let(MangaDexRelation::fromDex)
}
}
)
}
}

View File

@ -11,6 +11,7 @@ import exh.md.dto.ChapterDto
import exh.md.dto.ChapterListDto
import exh.md.dto.MangaDto
import exh.md.dto.MangaListDto
import exh.md.dto.RelationListDto
import exh.md.dto.ResultDto
import exh.md.utils.MdApi
import exh.md.utils.MdConstants
@ -145,6 +146,21 @@ class MangaDexService(
): AtHomeDto {
return client.newCall(GET(atHomeRequestUrl, headers, CacheControl.FORCE_NETWORK))
.await()
.parseAs()
.parseAs(MdUtil.jsonParser)
}
suspend fun relatedManga(id: String): RelationListDto {
return client.newCall(
GET(
MdApi.manga.toHttpUrl().newBuilder()
.apply {
addPathSegment(id)
addPathSegment("relation")
}
.build()
.toString(),
cache = CacheControl.FORCE_NETWORK
)
).await().parseAs(MdUtil.jsonParser)
}
}

View File

@ -2,9 +2,12 @@ package exh.md.similar
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.source.model.MetadataMangasPage
import eu.kanade.tachiyomi.source.online.all.MangaDex
import eu.kanade.tachiyomi.ui.browse.source.browse.NoResultsException
import eu.kanade.tachiyomi.ui.browse.source.browse.Pager
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
/**
* MangaDexSimilarPager inherited from the general Pager.
@ -12,7 +15,18 @@ import eu.kanade.tachiyomi.ui.browse.source.browse.Pager
class MangaDexSimilarPager(val manga: Manga, val source: MangaDex) : Pager() {
override suspend fun requestNextPage() {
val mangasPage = source.getMangaSimilar(manga.toMangaInfo())
val mangasPage = coroutineScope {
val similarPageDef = async { source.getMangaSimilar(manga.toMangaInfo()) }
val relatedPageDef = async { source.getMangaRelated(manga.toMangaInfo()) }
val similarPage = similarPageDef.await()
val relatedPage = relatedPageDef.await()
MetadataMangasPage(
relatedPage.mangas + similarPage.mangas,
false,
relatedPage.mangasMetadata + similarPage.mangasMetadata
)
}
if (mangasPage.mangas.isNotEmpty()) {
onPageReceived(mangasPage)

View File

@ -0,0 +1,27 @@
package exh.md.utils
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
enum class MangaDexRelation(@StringRes val resId: Int, val mdString: String?) {
SIMILAR(R.string.relation_similar, null),
MONOCHROME(R.string.relation_monochrome, "monochrome"),
MAIN_STORY(R.string.relation_main_story, "main_story"),
ADAPTED_FROM(R.string.relation_adapted_from, "adapted_from"),
BASED_ON(R.string.relation_based_on, "based_on"),
PREQUEL(R.string.relation_prequel, "prequel"),
SIDE_STORY(R.string.relation_side_story, "side_story"),
DOUJINSHI(R.string.relation_doujinshi, "doujinshi"),
SAME_FRANCHISE(R.string.relation_same_franchise, "same_franchise"),
SHARED_UNIVERSE(R.string.relation_shared_universe, "shared_universe"),
SEQUEL(R.string.relation_sequel, "sequel"),
SPIN_OFF(R.string.relation_spin_off, "spin_off"),
ALTERNATE_STORY(R.string.relation_alternate_story, "alternate_story"),
PRESERIALIZATION(R.string.relation_preserialization, "preserialization"),
COLORED(R.string.relation_colored, "colored"),
SERIALIZATION(R.string.relation_serialization, "serialization");
companion object {
fun fromDex(mdString: String) = values().find { it.mdString == mdString }
}
}

View File

@ -2,6 +2,7 @@ package exh.metadata.metadata
import android.content.Context
import eu.kanade.tachiyomi.R
import exh.md.utils.MangaDexRelation
import exh.md.utils.MdUtil
import exh.metadata.metadata.base.RaisedSearchMetadata
import kotlinx.serialization.Serializable
@ -40,6 +41,7 @@ class MangaDexSearchMetadata : RaisedSearchMetadata() {
// var missing_chapters: String? = null
var followStatus: Int? = null
var relation: MangaDexRelation? = null
// var maxChapterNumber: Int? = null

View File

@ -669,6 +669,24 @@
<!-- Similar -->
<string name="similar">Similar to %1$s</string>
<string name="similar_no_results">No Similar Manga found</string>
<!-- Mangadex relations-->
<string name="relation_similar">Similar</string>
<string name="relation_monochrome">Monochrome</string>
<string name="relation_main_story">Main story</string>
<string name="relation_adapted_from">Adapted from</string>
<string name="relation_based_on">Based on</string>
<string name="relation_prequel">Prequel</string>
<string name="relation_side_story">Side story</string>
<string name="relation_doujinshi">Doujinshi</string>
<string name="relation_same_franchise">Same franchise</string>
<string name="relation_shared_universe">Shared universe</string>
<string name="relation_sequel">Sequel</string>
<string name="relation_spin_off">Spin-off</string>
<string name="relation_alternate_story">Alternate story</string>
<string name="relation_preserialization">Pre-serialization</string>
<string name="relation_colored">Colored</string>
<string name="relation_serialization">Serialization</string>
<!-- Humanize time -->
<plurals name="humanize_year">