diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt index 97cbc415c..ca6817860 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt @@ -4,6 +4,7 @@ import android.content.Context import android.net.Uri import eu.kanade.tachiyomi.network.asObservableSuccess 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.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource @@ -14,6 +15,8 @@ import exh.metadata.metadata.TsuminoSearchMetadata.Companion.TAG_TYPE_DEFAULT import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL import exh.metadata.metadata.base.RaisedTag import exh.source.DelegatedHttpSource +import exh.util.dropBlank +import exh.util.trimAll import exh.util.urlImportFetchSearchManga import java.text.SimpleDateFormat import java.util.Locale @@ -28,13 +31,13 @@ class Tsumino(delegate: HttpSource, val context: Context) : override val lang = "en" // Support direct URL importing - override fun fetchSearchManga(page: Int, query: String, filters: FilterList) = + override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable = urlImportFetchSearchManga(context, query) { super.fetchSearchManga(page, query, filters) } override fun mapUrlToMangaUrl(uri: Uri): String? { - val lcFirstPathSegment = uri.pathSegments.firstOrNull()?.toLowerCase() ?: return null + val lcFirstPathSegment = uri.pathSegments.firstOrNull()?.toLowerCase(Locale.ROOT) ?: return null if (lcFirstPathSegment != "read" && lcFirstPathSegment != "book" && lcFirstPathSegment != "entry") { return null } @@ -58,9 +61,12 @@ class Tsumino(delegate: HttpSource, val context: Context) : title = it.trim() } - input.getElementById("Artist")?.children()?.first()?.text()?.trim()?.let { - tags.add(RaisedTag("artist", it, TAG_TYPE_VIRTUAL)) - artist = it + input.getElementById("Artist")?.children()?.first()?.text()?.trim()?.let { artistString -> + artistString.split("|").trimAll().dropBlank().forEach { + tags.add(RaisedTag("artist", it, TAG_TYPE_DEFAULT)) + } + tags.add(RaisedTag("artist", artistString, TAG_TYPE_VIRTUAL)) + artist = artistString } input.getElementById("Uploader")?.children()?.first()?.text()?.trim()?.let { @@ -86,18 +92,19 @@ class Tsumino(delegate: HttpSource, val context: Context) : input.getElementById("Collection")?.children()?.first()?.text()?.let { collection = it.trim() + tags.add(RaisedTag("collection", it, TAG_TYPE_DEFAULT)) } input.getElementById("Group")?.children()?.first()?.text()?.let { group = it.trim() - tags.add(RaisedTag("group", it, TAG_TYPE_VIRTUAL)) + tags.add(RaisedTag("group", it, TAG_TYPE_DEFAULT)) } val newParody = mutableListOf() input.getElementById("Parody")?.children()?.forEach { val entry = it.text().trim() newParody.add(entry) - tags.add(RaisedTag("parody", entry, TAG_TYPE_VIRTUAL)) + tags.add(RaisedTag("parody", entry, TAG_TYPE_DEFAULT)) } parody = newParody @@ -105,14 +112,14 @@ class Tsumino(delegate: HttpSource, val context: Context) : input.getElementById("Character")?.children()?.forEach { val entry = it.text().trim() newCharacter.add(entry) - tags.add(RaisedTag("character", entry, TAG_TYPE_VIRTUAL)) + tags.add(RaisedTag("character", entry, TAG_TYPE_DEFAULT)) } character = newCharacter - input.getElementById("Tag")?.children()?.let { + input.getElementById("Tag")?.children()?.let { tagElements -> tags.addAll( - it.map { - RaisedTag(null, it.text().trim(), TAG_TYPE_DEFAULT) + tagElements.map { + RaisedTag("tags", it.text().trim(), TAG_TYPE_DEFAULT) } ) } @@ -126,6 +133,5 @@ class Tsumino(delegate: HttpSource, val context: Context) : companion object { val TM_DATE_FORMAT = SimpleDateFormat("yyyy MMM dd", Locale.US) - private val ASP_NET_COOKIE_NAME = "ASP.NET_SessionId" } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index eb303c329..295be9c97 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -37,6 +37,7 @@ import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.source.online.LewdSource import eu.kanade.tachiyomi.ui.base.controller.FabController import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction @@ -69,6 +70,9 @@ import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.shrinkOnScroll import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.visible +import exh.metadata.metadata.base.FlatMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata +import exh.source.EnhancedHttpSource import java.io.IOException import kotlinx.android.synthetic.main.main_activity.root_coordinator import kotlinx.coroutines.CancellationException @@ -419,6 +423,16 @@ class MangaController : // Manga info - start + // SY --> + fun onNextMetaInfo(flatMetadata: FlatMetadata) { + presenter.meta = if (presenter.source is LewdSource<*, *>) { + flatMetadata.raise((presenter.source as LewdSource<*, *>).metaClass) + } else if (presenter.source is EnhancedHttpSource && (presenter.source as EnhancedHttpSource).enhancedSource is LewdSource<*, *>) { + flatMetadata.raise(((presenter.source as EnhancedHttpSource).enhancedSource as LewdSource<*, *>).metaClass) + } else null + } + // SY <-- + /** * Check if manga is initialized. * If true update header with manga information, @@ -427,10 +441,10 @@ class MangaController : * @param manga manga object containing information about manga. * @param source the source of the manga. */ - fun onNextMangaInfo(manga: Manga, source: Source) { + fun onNextMangaInfo(manga: Manga, source: Source /* SY --> */, meta: RaisedSearchMetadata? /* SY <-- */) { if (manga.initialized) { // Update view. - mangaInfoAdapter?.update(manga, source) + mangaInfoAdapter?.update(manga, source /* SY --> */, meta /* SY <-- */) } else { // Initialize manga. fetchMangaInfoFromSource() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index be792c65e..f5ce220f2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt @@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.Source +import eu.kanade.tachiyomi.source.online.LewdSource import eu.kanade.tachiyomi.source.online.all.MergedSource import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem @@ -33,6 +34,10 @@ import exh.MERGED_SOURCE_ID import exh.debug.DebugToggles import exh.eh.EHentaiUpdateHelper import exh.isEhBasedSource +import exh.metadata.metadata.base.FlatMetadata +import exh.metadata.metadata.base.RaisedSearchMetadata +import exh.metadata.metadata.base.getFlatMetadataForManga +import exh.source.EnhancedHttpSource import exh.util.await import exh.util.trimOrNull import java.util.Date @@ -101,15 +106,23 @@ class MangaPresenter( private val redirectUserRelay = BehaviorRelay.create() data class EXHRedirect(val manga: Manga, val update: Boolean) + + var meta: RaisedSearchMetadata? = null // EXH <-- override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) + // SY --> + if (manga.initialized && (source is LewdSource<*, *> || (source is EnhancedHttpSource && source.enhancedSource is LewdSource<*, *>))) { + getMangaMetaObservable().subscribeLatestCache({ view, flatMetadata -> if (flatMetadata != null) view.onNextMetaInfo(flatMetadata) else Timber.d("Invalid metadata") }) + } + // SY <-- + // Manga info - start getMangaObservable() - .subscribeLatestCache({ view, manga -> view.onNextMangaInfo(manga, source) }) + .subscribeLatestCache({ view, manga -> view.onNextMangaInfo(manga, source /* SY --> */, meta/* SY <-- */) }) // Prepare the relay. chaptersRelay.flatMap { applyChapterFilters(it) } @@ -177,6 +190,16 @@ class MangaPresenter( .observeOn(AndroidSchedulers.mainThread()) } + // SY --> + private fun getMangaMetaObservable(): Observable { + val mangaId = manga.id + return if (mangaId != null) { + db.getFlatMetadataForManga(mangaId).asRxObservable() + .observeOn(AndroidSchedulers.mainThread()) + } else Observable.just(null) + } + // SY <-- + /** * Fetch manga information from source. */ @@ -190,6 +213,13 @@ class MangaPresenter( db.insertManga(manga).executeAsBlocking() manga } + // SY --> + .doOnNext { + if (source is LewdSource<*, *> || (source is EnhancedHttpSource && source.enhancedSource is LewdSource<*, *>)) { + getMangaMetaObservable().subscribeLatestCache({ view, flatMetadata -> if (flatMetadata != null) view.onNextMetaInfo(flatMetadata) else Timber.d("Invalid metadata") }) + } + } + // SY <-- .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeFirst( @@ -259,7 +289,7 @@ class MangaPresenter( .observeOn(AndroidSchedulers.mainThread()) .subscribeLatestCache( { view, _ -> - view.onNextMangaInfo(manga, source) + view.onNextMangaInfo(manga, source /* SY --> */, meta/* SY <-- */) } ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt index 7cac57584..5be97676e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt @@ -30,12 +30,9 @@ import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.setTooltip import eu.kanade.tachiyomi.util.view.visible import eu.kanade.tachiyomi.util.view.visibleIf -import exh.EH_SOURCE_ID -import exh.EXH_SOURCE_ID -import exh.HITOMI_SOURCE_ID import exh.MERGED_SOURCE_ID -import exh.NHENTAI_SOURCE_ID -import exh.PURURIN_SOURCE_ID +import exh.isNamespaceSource +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.util.SourceTagsUtil import exh.util.makeSearchChip import exh.util.setChipsExtended @@ -57,6 +54,7 @@ class MangaInfoHeaderAdapter( private var manga: Manga = controller.presenter.manga private var source: Source = controller.presenter.source + private var meta: RaisedSearchMetadata? = controller.presenter.meta private val scope = CoroutineScope(Job() + Dispatchers.Main) private lateinit var binding: MangaInfoHeaderBinding @@ -83,9 +81,10 @@ class MangaInfoHeaderAdapter( * @param manga manga object containing information about manga. * @param source the source of the manga. */ - fun update(manga: Manga, source: Source) { + fun update(manga: Manga, source: Source, meta: RaisedSearchMetadata?) { this.manga = manga this.source = source + this.meta = meta notifyDataSetChanged() } @@ -336,7 +335,7 @@ class MangaInfoHeaderAdapter( // Update genres list if (!manga.genre.isNullOrBlank()) { // SY --> - if (source != null && (source.id == EH_SOURCE_ID || source.id == EXH_SOURCE_ID || source.id == NHENTAI_SOURCE_ID || source.id == HITOMI_SOURCE_ID || source.id == PURURIN_SOURCE_ID)) { + if (source != null && source.isNamespaceSource()) { val genre = manga.getGenres() if (!genre.isNullOrEmpty()) { val namespaceTags = genre.map { SourceTagsUtil().parseTag(it) } @@ -414,7 +413,7 @@ class MangaInfoHeaderAdapter( binding.mangaGenresTagsCompact.visibleIf { isExpanded } // SY --> - if (source.id == EH_SOURCE_ID || source.id == EXH_SOURCE_ID || source.id == NHENTAI_SOURCE_ID || source.id == HITOMI_SOURCE_ID || source.id == PURURIN_SOURCE_ID) { + if (source.isNamespaceSource()) { binding.mangaNamespaceTagsRecycler.visibleIf { !isExpanded } } else { binding.mangaGenresTagsFullChips.visibleIf { !isExpanded } diff --git a/app/src/main/java/exh/EHSourceHelpers.kt b/app/src/main/java/exh/EHSourceHelpers.kt index f05a78ac7..a8f0ef3ae 100755 --- a/app/src/main/java/exh/EHSourceHelpers.kt +++ b/app/src/main/java/exh/EHSourceHelpers.kt @@ -57,3 +57,5 @@ fun isLewdSource(source: Long) = source in 6900..6999 || lewdDelegatedSourceIds.binarySearch(source) >= 0 fun Source.isEhBasedSource() = id == EH_SOURCE_ID || id == EXH_SOURCE_ID + +fun Source.isNamespaceSource() = id == EH_SOURCE_ID || id == EXH_SOURCE_ID || id == NHENTAI_SOURCE_ID || id == HITOMI_SOURCE_ID || id == PURURIN_SOURCE_ID || id == TSUMINO_SOURCE_ID diff --git a/app/src/main/java/exh/util/SourceTagsUtil.kt b/app/src/main/java/exh/util/SourceTagsUtil.kt index 1716885ba..b6a4bd957 100644 --- a/app/src/main/java/exh/util/SourceTagsUtil.kt +++ b/app/src/main/java/exh/util/SourceTagsUtil.kt @@ -5,6 +5,7 @@ import exh.EXH_SOURCE_ID import exh.HITOMI_SOURCE_ID import exh.NHENTAI_SOURCE_ID import exh.PURURIN_SOURCE_ID +import exh.TSUMINO_SOURCE_ID class SourceTagsUtil { fun getWrappedTag(sourceId: Long, namespace: String? = null, tag: String? = null, fullTag: String? = null): String? { @@ -15,6 +16,7 @@ class SourceTagsUtil { HITOMI_SOURCE_ID -> wrapTagHitomi(parsed.first, parsed.second.substringBefore('|').trim()) NHENTAI_SOURCE_ID -> wrapTagNHentai(parsed.first, parsed.second.substringBefore('|').trim()) PURURIN_SOURCE_ID -> parsed.second.substringBefore('|').trim() + TSUMINO_SOURCE_ID -> parsed.second.substringBefore('|').trim() else -> wrapTag(parsed.first, parsed.second.substringBefore('|').trim()) } } else null